#ifndef VOICETHREAD_H
#define VOICETHREAD_H

#include <QObject>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QObject>
#include <QThread>
#include <QAudioBuffer> //音频缓存
#include <QAudioInput>
#include <QObject>
#include <QJsonDocument>
#include <QApplication>
#include <QJsonObject>
#include <QThread>
#include <ukui-log4qt.h>
#include <QAudioOutput>
#include <QAudioFormat>
#include <QAudioDecoder>
#include <QIODevice>
#include <QThread>
#include <QTemporaryFile>
#include <QQueue>
#include <QMutex>
#include <QWaitCondition>
#include <QMediaPlayer>
#include <QQueue>
#include <QByteArray>
#include <QClipboard>

#include "global/kaglobal.h"

#include <kylin-ai/coreai/speech/recognizer.h>
#include <kylin-ai/coreai/speech/audioconfig.h>
#include <kylin-ai/coreai/speech/error.h>
#include <kylin-ai/coreai/speech/result.h>
#include <kylin-ai/coreai/speech/synthesizer.h>
#include <aiconfig/modelconfig.h>
#include <kylin-ai/common/macros.h>
#include <kylin-ai/private/osassistant/osassistant.h>
#include <common/error.h>

#include "chatdatabase.h"

#include "voicechatreader.h"
#include "voicechatreadercontrolproxy.h"
#include "voicechatspeech.h"
#include "voicechatspeechcontrolproxy.h"
#include "voicechatanswer.h"

class CMainWnd;



class VoiceThread : public QThread
{
    Q_OBJECT
    Q_PROPERTY(VoiceChatState currentVoiceState READ getCurVoiceState NOTIFY voiceStateChanged)
    Q_PROPERTY(int currentMicVolume READ getCurVoiceVolume NOTIFY voiceMicVolumeChanged)
public:
    explicit VoiceThread(QObject *parent = nullptr);
    ~VoiceThread();

    // 语音通话的标志位
    enum VoiceChatState {
        Idle = 0,        // 空闲状态
        Initializing,   // 初始化中（启动语音识别时）
        Recording,      // 录音中
        SendQuestioning, //发送问题中
        Recognizing,    // 识别中
        Answering,      // 回答中
        Reading,        // 朗读中
        Finish,         // 通话完成
    };
    Q_ENUM(VoiceChatState) // 注册枚举到元对象系统

    VoiceThread::VoiceChatState getCurVoiceState() const;
    int getCurVoiceVolume() const ;
    Q_INVOKABLE bool isOndeviceSpeechModel() const;

    static VoiceThread *getPtr();

    void initVoiceThread();

    void stopThread();
    void clearContext();
    void sendQuestion(QString text, QString filePath);

    void initConnect();
    void initChildModule();
    /**
     * @brief setNlpModel
     * @param name
     */
    void setNlpModel(QString name);

    /**
     * @brief 设置深度思考
     * @param checked
     */
    void setDeepThinking(bool checked);

    /**
     * @brief 设置联网搜索
     * @param checked
     */
    void setWebSearch(bool checked);


signals:
    /* 所有消息都通过这个信号接口向QML端返回通知消息，禁止添加额外接口，应通过在参数里新增字段。该参数为一个json对象。
     * 遵守的格式如下，其中msgType为字符串，标识当前消息的分类。msgBody为一个json对象，用于携带具体的参数。
     * {"msgType":"xxx", "msgBody":{}}
     */
    void receiveMessage(const QString message);

    /**
     * @brief 语音状态变更
     * @param 无
     */
    void voiceStateChanged();

    /**
     * @brief 音量变化
     */
    void voiceMicVolumeChanged();

    /**
     * @brief 删除数据的结果
     * @param 唯一索引
     * @param 对话中msg索引
     * @param 删除结果
     */
    void deleteAnswerResult(const int uniqueIndex, const int msgIndex, const bool result);

    /**
     * @brief 重置唯一索引和模型列表信号
     */
    void resetUniqueIndexAndModelList();

    /**
     * @brief 打断成功
     */
    void sigInterruptSuccessful();

    /**
     * @brief 当前音量数据
     * @param 音量
     */
    void sigCurrentVoiceNumber(const int number);

public slots:
    /* 所有消息都通过这个接口从QML端发送消息，禁止添加额外接口，应通过在参数里新增字段。该参数为一个json对象。
     * 遵守的格式如下，其中msgType为字符串，标识当前消息的分类。msgBody为一个json对象，用于携带具体的参数。
     * {"msgType":"xxx", "msgBody":{}}
     */
    Q_INVOKABLE void sendMessage(const QString message);

    /* 所有同步消息(即调用需要返回值的场景)都通过这个接口从QML端发送消息，禁止添加额外接口，应通过在参数里新增字段。该参数为一个json对象。
     * 遵守的格式如下，其中msgType为字符串，标识当前消息的分类。msgBody为一个json对象，用于携带具体的参数。
     * {"msgType":"xxx", "msgBody":{}}
     * 返回值格式为： {"msgType":"xxx", "msgBody":{}}
     */
    Q_INVOKABLE QString sendMessageSync(const QString message);

public slots:
    // 语音通话控制部分
    bool startVoiceChat();
    void pauseVoiceChat();
    void continueVoiceChat();
    /**
     * @brief 停止语音通话
     */
    void stopVoiceChat();

    /**
     * @brief 更新语音通话的索引
     */
    void updateVoiceChatIndex();
    ///
    /// \brief 打断语音回复
    ///
    void interruptReply();

    /**
     * @brief 打断回答结束
     */
    void interruptReplyEnd();


    void stopReply();

    // 语音转文字模块
    /**
     * @brief 关闭语音识别会话
     */
    void closeSpeechSession();

    /**
     * @brief 获取持续语音识别结果
     * @param 结果字符串
     */
    void slGetSpeechRecognitionResult(const QString message);

    /**
     * @brief 更新当前音量
     * @param 当前音量
     */
    void slUpdateCurrnetVolume(const int curVolume);

    // 大模型回答模块

    /**
     * @brief 关闭回答会话
     */
    void closeAnswerSession();

    /**
     * @brief 获取文本回复结果
     * @param msg
     */
    void getAnswerTextReslut(const QString msg);
    // 回答朗读模块
    /**
     * @brief 启动朗读
     * @param 待朗读信息
     * @param 索引
     */
    void startReading(const QString &msg, int index);

    ///
    /// \brief 发送待朗读文字
    /// \param 文字信息
    /// \param 当前朗读文字所在气泡索引
    ///
    void pushWaitingReadText(const QString &msg, int index);

    /**
     * @brief 停止阅读
     */
    void stopReading();

    /**
     * @brief 关闭阅读器会话
     */
    void closeReaderSession();

    /**
     * @brief 当前朗读结束
     */
    void onCurrentReadingEnd();

    /**
     * @brief 显示朗读错误信息
     * @param errorMsg
     */
    void onShowReadingError(const QString errorMsg);

    //功能函数模块
    /**
     * @brief 发送拷贝数据,实现拷贝功能
     * @param 数据
     */
    void sendCopyText(const QJsonObject &data);

    ///
    /// \brief 启动单个回答的朗读功能
    /// \param 待朗读数据
    /// \param 索引
    ///
    void startSingleAnswerReading(const QString  &data, const int index);

    ///
    /// \brief 设置启动回答状态，在首次回复内容时发送信号并处理此状态
    ///
    void setAnswerStatue();

    ///
    /// \brief 暂停当个回答的朗读功能
    ///
    void pauseSingleAnswerReading(const int index);

    ///
    /// \brief 处理前端的重置状态信号，封装为标准信号后并发送
    /// \param index
    ///
    void parseResetSingleAnswerReading(const int &index);

    ///
    /// \brief 继续单次朗读
    /// \param 索引
    ///
    void contiueSingleAnswerReading(const int index);

    //会话数据库管理模块
    /**
     * @brief 设置语音通话ID
     * @param 语音通话ID
     */
    void setVoiceID(int voiceID);

    /**
     * @brief 获取语音通话ID
     * @return 语音通话ID
     */
    int getVoiceID();

    /**
     * @brief 保存数据到数据库
     * @param 当前数据的唯一索引，数据唯一索引是为了保证数据在被删除时不影响实际的listmodel显示
     * @param 当前信息
     */
    Q_INVOKABLE void saveItemToDatabase(const int uniqueIndex, const QString msg);

    /**
     * @brief 基于索引删除信息
     * @param 当前数据的唯一索引
     */
    Q_INVOKABLE void deleteMessageByIndex(int uniqueIndex, int msgIndex);

    /**
     * @brief 获取打断状态
     * @return
     */
    Q_INVOKABLE bool getCurInterrupt();

public slots:
    /**
     * @brief 结束线程
     */
    void quitThread();

protected:
    void run();

private:
    /**
     * @brief 状态设置函数
     * @param 当前最新状态
     */
    void setVoiceState(VoiceChatState newState);
    /**
     * @brief 问题发送函数
     * @param 数据
     */
    void sendVoiceQuestion(const QJsonObject &data);

public:
    TartgetType target = RECVMSG;
    bool is_end;
    QString result_msg;
    int result_index;
    QString reasoningContentMsg;//深度思考内容
    QString text;
    int m_voiceID; //用于区分不同通话场次
    ChatDatabase *m_database = nullptr;    //数据库
    VoiceChatState m_currentVoiceState = VoiceChatState::Idle; // 当前录音状态
    int m_currentVoiceVolume = 0; // 当前录音音量
    bool is_Interrupting = false; // 是否正在执行打断，执行打断时，不发送待朗读内容
    bool is_stopingVoice = false; // 当前是否在执行停止语音通话
private:
    CMainWnd* mMainWnd = nullptr;
    VoiceChatAnswer *m_chatAnswer = nullptr;
    VoiceChatSpeech *m_chatSpeech = nullptr;
    VoiceChatReader *m_chatReader = nullptr;
    QClipboard *mClipboard = nullptr;
    
    // 工作线程和代理对象
    QThread *m_readerThread = nullptr;  // VoiceChatReader 的工作线程
    QThread *m_speechThread = nullptr;   // VoiceChatSpeech 的工作线程
    VoiceChatReaderControlProxy *m_readerProxy = nullptr;  // VoiceChatReader 的代理
    VoiceChatSpeechControlProxy *m_speechProxy = nullptr;  // VoiceChatSpeech 的代理

};

#endif // VOICETHREAD_H
