#include <QThread>
#include <ukui-log4qt.h>
#include "recorder.h"
#include <QIODevice>

/**
 * @brief chatCallback
 *          聊天结果返回回调函数，数据流式返回
 * @param result
 * @param usr_data
 */
static void speechCallback(RecognitionResult result, void *usr_data)
{
    if (usr_data == nullptr) {
        qDebug() << "Invalid callback user data pointer.";
    }
    Recorder *recorder = (Recorder*)usr_data;
    emit recorder->sigSendMsg("",result.text_data);
}

Recorder::Recorder(QObject *parent) : QObject(parent)
{
    //设置录音格式
    m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
    m_audioFormat.setChannelCount(1);
    m_audioFormat.setCodec("audio/pcm");
    m_audioFormat.setSampleRate(16000);
    m_audioFormat.setSampleSize(16);
    m_audioFormat.setSampleType(QAudioFormat::SignedInt);

    // 判断设备，查看是否存在
    QAudioDeviceInfo devInfo = QAudioDeviceInfo::defaultInputDevice();
    if (devInfo.isNull()) {
        qWarning() << "No recording device was found!";
    }
    // 不支持格式，使用最接近格式
    if (!devInfo.isFormatSupported(m_audioFormat)) {  // 当前使用设备是否支持
        qWarning() << "Automatic conversion is made to the nearest format!";
        m_audioFormat = devInfo.nearestFormat(m_audioFormat);  // 转换为最接近格式
    }

    m_audioInput = new QAudioInput(devInfo, m_audioFormat, this);
    connect(m_audioInput, &QAudioInput::stateChanged, this, &Recorder::handleStateChanged);

    m_audioInput->setNotifyInterval(10 * 1000);
    initSession();

}

Recorder::~Recorder()
{
    if (m_audioInput != nullptr) {
        m_audioInput->stop();
        delete m_audioInput;
    }

}

//单次语音处理
void Recorder::startRecord()
{
    qDebug() << "startRecord";

    m_audioBuffer.open( QIODevice::ReadWrite | QIODevice::Truncate );

    m_audioInput->start(&m_audioBuffer);

//    QTimer::singleShot(30 * 1000, this, &Recorder::stopRecord);
}

void Recorder::stopRecord()
{
    m_audioInput->stop();
    onReadInfo();

}

void Recorder::sendAudio(const void *audio_data, unsigned int audio_data_length)
{
    QJsonObject jsonObject;
    jsonObject["format"] = "pcm";
    jsonObject["rate"] = 16000;
    jsonObject["channel"] = 1;
    const char *params = QJsonDocument(jsonObject).toJson(QJsonDocument::Indented);

    SpeechResult result = speech_recognize_once_async(this->session, params, audio_data, audio_data_length);
    if (result != SPEECH_SUCCESS){
        qDebug() <<  "speech_recognize_once_async error";
    }
}

void Recorder::onReadInfo()
{
    m_audioBuffer.close();
    m_audioBuffer.open(QIODevice::ReadOnly);
    QByteArray data = m_audioBuffer.readAll();

    qDebug() <<  "QByteArray data" << data.length();

    if (data.length() != 0)
        sendAudio(data.data(), data.length());
}



bool Recorder::initSession()
{
//    QThread::create([this]{
        void *session = nullptr;
        SpeechResult ret = speech_create_session(&session);
        if (ret != SPEECH_SUCCESS || session == nullptr){
            KyInfo() << "speech create session error:" << ret;
            return false;
        }
        ret = speech_init_session(session);
        if (ret != SPEECH_SUCCESS){
            KyInfo() << "speech init session error :" << ret;
            return false;
        }
//    })->start();

    this->session = session;
    speech_set_recognizing_callback(this->session, speechCallback, this);

    return true;

}

void Recorder::closeSession()
{
    if(this->session != nullptr)
        speech_destory_session(this->session);
}

void Recorder::handleStateChanged(QAudio::State state)
{
    qDebug() <<  "handleStateChanged" << state;
    switch (state) {
        case QAudio::StoppedState: {
            if (m_audioInput->error() != QAudio::NoError) {
                qCritical() << "Sound recording error!";
            }
        } break;
        case QAudio::ActiveState: {
            qInfo() << "Start recording the sound...";
        } break;
        default:
            break;
    }
}
