/*
 * Copyright (C) 2020, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
#ifndef READER_H
#define READER_H

#include <QObject>
#include <QFile>
#include <QMutex>
#include "msgpane.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 <kylin-ai/coreai/speech/synthesizer.h>
#include <kylin-ai/coreai/speech/audioconfig.h>
//#include <kylin-ai/coreai/speech/error.h>
#include <kylin-ai/coreai/speech/result.h>


//TODO: 实时朗读
#if 0
class AudioPlayer : public QObject
{
    Q_OBJECT

public:
    AudioPlayer(QObject *parent = nullptr)
        : QObject(parent), m_mediaPlayer(new QMediaPlayer(this))
    {
//        connect(m_mediaPlayer, &QMediaPlayer::mediaStatusChanged, this, &AudioPlayer::onMediaStatusChanged);
    }

    ~AudioPlayer()
    {
        // 停止媒体播放器并清理资源
        m_mediaPlayer->stop();
        delete m_mediaPlayer;
    }

    void enqueueAudio(const QByteArray &audioData)
    {
        m_playQueue.enqueue(audioData);
        if (m_mediaPlayer->state() != QMediaPlayer::PlayingState) {
            playNextAudio();
        }
    }

signals:
    void audioPlaybackFinished();

private slots:
    void onMediaStatusChanged(QMediaPlayer::MediaStatus status)
    {
        //KyInfo()<<"status ========= "<<status <<"EndOfMedia = "<<QMediaPlayer::EndOMedia;
        if (status == QMediaPlayer::EndOfMedia) {
            // 播放结束，准备下一次播放
            playNextAudio();
        }
        else if (status == QMediaPlayer::InvalidMedia)
        {
            KyInfo()<<"数据异常";
            //m_mediaPlayer->play();
        }
    }

    void playNextAudio()
    {
        if (!m_playQueue.isEmpty()) {
            QByteArray audioData = m_playQueue.dequeue();
            // 假设这里有一个将QByteArray转换为QMediaPlayer可以播放的格式的方法
            // 例如，将数据写入一个临时文件并设置给媒体播放器
            QTemporaryFile tempFile;
            if (tempFile.open()) {
                tempFile.write(audioData);
                tempFile.close();
                m_mediaPlayer->setMedia(QUrl::fromLocalFile(tempFile.fileName()));

                KyInfo()<<"QUrl::fromLocalFile(tempFile.fileName()) = "<<QUrl::fromLocalFile(tempFile.fileName());
                m_mediaPlayer->play();
                KyInfo()<<"m_textSoundFlag = "<<m_textSoundFlag;
            } else {
                KyInfo() << "Failed to open temporary file";
            }
        } else {
            // 队列为空，可以发出播放结束信号或进行其他处理
            KyInfo()<<"队列为空，可以发出播放结束信号或进行其他处理 m_textSoundFlag= "<<m_textSoundFlag;
            Q_EMIT audioPlaybackFinished();
        }
    }
public:
    bool m_textSoundFlag = false;

private:
    QMediaPlayer *m_mediaPlayer;
    QQueue<QByteArray> m_playQueue; // 使用QQueue作为音频数据队列
};
#endif

class Reader : public QObject
{
    Q_OBJECT
public:
    explicit Reader(QObject *parent = nullptr);
    ~Reader();
    void startReading();
    void pauseReading();
    void continueReading(int index);
    bool sendText(const QString &msg, int index);
    void closeSession();
    QFile *m_file;
    bool m_soundFlag = false;           //标志位，用于区分实时朗读和普通朗读
    int m_index = -1;
    bool isNeedRead;                      //合成音频过程中，记录用户暂停操作，如果用户暂停，合成结束后不朗读。

signals:
    void sigReadEnd(int index);
    void reply(const QString &message,bool is_end,int index, int errorCode, QString model = "");
    void sigResetPreIndex();    //发送信号，重置前端preIndex值。  点击朗读失败时触发。
public slots:
    void onPlayerStateChanged(QMediaPlayer::MediaStatus status);

private:
    SpeechSynthesizerSession *session = nullptr;
    QMediaPlayer * m_player = nullptr;

    bool initSession();
    void initConnect();
    QString generateUniqueFileName();
};

#endif // READER_H
