#ifndef VOICECHATREADER_H
#define VOICECHATREADER_H

#include <QObject>
#include <QObject>
#include <QFile>
#include <QMutex>
#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 <ukui-log4qt.h>

#include <kylin-ai/coreai/speech/synthesizer.h>
#include <kylin-ai/coreai/speech/audioconfig.h>
#include <kylin-ai/coreai/speech/result.h>

#include "global/kaglobal.h"
#include "voicechat/sdl2audioplayerthread.h"

#define READ_FILE_PATH "/.read"


///
/// \brief 语音对话中的回答朗读模块，模拟机器人对回复进行朗读达到语音回复的效果
///
class VoiceChatReader : public QObject
{
    Q_OBJECT
public:
    explicit VoiceChatReader(QObject *parent = nullptr);
    ~VoiceChatReader();
    /**
     * @brief 初始化信号槽连接
     */
    void initConnect();

    /**
     * @brief 将对象移动到工作线程
     * @param thread 目标线程
     */
    void moveToWorkerThread(QThread *thread);

signals:
    /**
     * @brief 朗读结束信号
     * @param 索引
     */
    void sigReadEnd(int index);
    ///
    /// \brief 朗读回复
    /// \param message
    /// \param is_end
    /// \param index
    /// \param errorCode
    /// \param model
    ///
    void reply(const QString &message,bool is_end,int index, int errorCode, QString model = "");
    ///
    /// \brief 重置索引信号，点击朗读失败时触发。
    ///
    void sigResetPreIndex();    //发送信号，重置前端preIndex值。  点击朗读失败时触发。
    /**
     * @brief 朗读合成信息信号，发送到控制模块并转发到前端生成气泡
     * @param 合成结果内容
     */
    void sigReceiveReaderMessage(const QString message);

    /**
     * @brief 启动播放信号
     */
    void sigPlayingStart();

public:
    // 文本合成语音朗读部分
    /**
     * @brief 初始化朗读会话
     * @return 朗读会话是否创建成功
     */
    Q_INVOKABLE bool initReaderSession();
    /**
     * @brief 关闭朗读会话
     * @return 朗读会话是否关闭成功
     */
    Q_INVOKABLE bool closeReaderSession();
    /**
     * @brief 启动朗读
     */
    Q_INVOKABLE void startReading();
    /**
     * @brief 暂停朗读
     */
    Q_INVOKABLE void pauseReading();
    /**
     * @brief 停止朗读
     */
    Q_INVOKABLE void stopReading();

    /**
     * @brief 继续阅读
     */
    Q_INVOKABLE void continueReading();

    /**
     * @brief 打断朗读
     */
    Q_INVOKABLE void interruptReading();

    /**
     * @brief 获取当前阅读状态
     * @return 返回当前是否正在朗读
     */
    Q_INVOKABLE bool getCurrentReaderStatus();
    /**
     * @brief 发送文本到合成器进行合成，合成完毕后自动触发朗读
     * @param 待合成文案
     * @param 当前索引
     * @return 是否合成成功
     */
    Q_INVOKABLE bool sendReadingText(const QString &msg, int index);

    /**
     * @brief 继续追加待朗读文本
     * @param 文本
     * @param 索引
     * @return 是否追加成功
     */
    Q_INVOKABLE bool continueAddReadingText(const QString &msg, int index);

    /**
     * @brief 获取当前朗读索引
     * @return 索引值
     */
    Q_INVOKABLE int getCurrentReadIndex();

    /**
     * @brief 插入待朗读文本
     * @param 文本信息
     * @return 是否插入成功
     */
    Q_INVOKABLE bool insertWaitingReadingListItem(const QString &msg);

    /**
     * @brief 清理待朗读列表
     */
    Q_INVOKABLE void clearWaitingReadingList();

    /**
     * @brief 更新当前待朗读文本
     */
    Q_INVOKABLE void updateCurReadIndex(const int &index);

    /**
     * @brief 解析和发送错误信息
     * @param 错误码
     */
    void parseAndSendErrorMsg(const int errorCode);

    /**
     * @brief convertMarkDownToHtml
     * @param markDown
     * @return
     */
    QString convertMarkDownToHtml(const QString &markDown);

    /**
     * @brief markdownToHtml
     * @param markdown
     * @return
     */
    QString markdownToHtml(const std::string& markdown);

private:
    SpeechSynthesizerSession *m_readerSession = nullptr;
    QThread *m_workerThread = nullptr;  // 工作线程指针
public:
    SDL2AudioPlayerThread *m_sdl2Player = nullptr;
    bool m_soundFlag = false;           //标志位，用于区分实时朗读和普通朗读
    bool isNeedRead;                      //合成音频过程中，记录用户暂停操作，如果用户暂停，合成结束后不朗读。
    int m_index = -1;
    bool m_isReaderSpeechSynthesizing;   //标志位，是否正在合成语音
    QStringList m_waitingReadingList; // 待朗读列表
};

#endif // VOICECHATREADER_H
