#include "PhaseDevice.h"
#include <iostream>
#include <QDateTime>
#include <QThread>
#include <QTimer>

PhaseDevice::PhaseDevice(QObject *parent) : QObject(parent)
{
    connect(&this->serialUtil, &QSerialPortUtil::dataRecieved,
            this, &PhaseDevice::dataReceivedHandler);

    kafkaUtil.setBrokers(SettingConfig::getInstance().KAFKA_BROKERS);
    kafkaUtil.setTopic(SettingConfig::getInstance().KAFKA_DATA_TOPIC);
    kafkaUtil.createProducer();
}

PhaseDevice::~PhaseDevice()
{
    disconnect(&this->serialUtil, &QSerialPortUtil::dataRecieved,
                this, &PhaseDevice::dataReceivedHandler);
}

void PhaseDevice::setComName(QString comName)
{
    this->comName = comName;
}
void PhaseDevice::setBaudRate(int baudRate)
{
    this->baudRate = baudRate;
}
QString PhaseDevice::getDevCode()
{
    return this->devCode;
}
void PhaseDevice::setDevCode(QString devCode)
{
    this->devCode = devCode;
}
void PhaseDevice::setDeviceId(QString deviceId)
{
    this->deviceId = deviceId;
}

bool PhaseDevice::isSerialOpen()
{
    return this->serialUtil.isOpen();
}

void PhaseDevice::initSerialPort()
{   
    int master = SettingConfig::getInstance().MASTER;
    QStringList comNameList = this->comName.split(",");
    if (comNameList.isEmpty() == true)
    {
        return;
    }

    // 如果是主程序则打开主串口 备程序则打开备串口
    if (master == 1)
    {
        this->serialUtil.openSerialPort(comNameList.at(0), this->baudRate);
    } else
    {
        this->serialUtil.openSerialPort(comNameList.at(1), this->baudRate);
    }
}

void PhaseDevice::startWork()
{
    QString startCmd = PhaseProtocolBM::startMessure();
    for (int i = 0; i < 3; i++) {
        this->serialUtil.sendData(startCmd.toLocal8Bit());
        QThread::msleep(100);
    }

    // temp code: auto stop after started AUTO_STOP_TIME hour
//    QTimer::singleShot(SettingConfig::getInstance().AUTO_STOP_TIME * 3600 * 1000, [=](){
//        stopWork();
//    });
}

void PhaseDevice::stopWork()
{
    QString stopCmd = PhaseProtocolBM::stopMessure();
    for (int i = 0; i < 3; i++) {
        this->serialUtil.sendData(stopCmd.toLocal8Bit());
        QThread::msleep(100);
    }
}

void PhaseDevice::dataReceivedHandler(QByteArray data)
{
    this->dataBuff.append(data);

//    std::cout << QByteUtil::binToHexString(this->dataBuff).toStdString() << std::endl;

    PhaseDataDto * phaseData = new PhaseDataDto(this);
    if (PhaseProtocolBM::checkFrame(this->dataBuff) == true)
    {
        phaseData->rawFrame = this->dataBuff;

        // ★解析成数据对象
        bool parse = PhaseProtocolBM::parseMessureData(this->dataBuff, phaseData);

        // 解析成功
        if (parse == true)
        {
            QDateTime now = QDateTime::currentDateTime();
            phaseData->devCode = this->devCode;
            phaseData->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz");
            phaseData->milisecond = now.toMSecsSinceEpoch();
            this->afterFramePhase(phaseData);
        }
    } else if (this->dataBuff.size() > PHASE_FRAM_LENGTH)
    {
        std::cout << QString("%1").arg(this->dataBuff.size()).toStdString() << std::endl;
        this->dataBuff.clear();
    }

    // 在此处释放内存，不影响后续显示
    // 不在此处释放内存则会导致内存持续增加
    // 具体原因不明
    delete phaseData;
}


void PhaseDevice::afterFramePhase(PhaseDataDto * phaseData)
{
    // 1. 清空dataBuff，等待下一帧的数据
    this->dataBuff.clear();

    // 2. 输出到日志文件中
    QString date = phaseData->timestamp.mid(0, 10);

    // 2.1 原始字节数组数据
    QString filename = "raw_" + devCode + ".log";
    QString content = phaseData->timestamp + " " + QByteUtil::binToHexString(phaseData->rawFrame);
    QLogUtil::writeRawDataLogByDate(date, filename, content);

    QJsonArray messageArray;

    // 2.2 各个通道的相差数据
    for (int i = 1; i <= phaseData->channelActive.size(); i++)
    {
        if (phaseData->channelActive.at(i-1).toUInt() == 1)
        {
            QString chFilename("%1_CH_%2.log");
            chFilename = chFilename.arg(devCode);
            if (i < 10)
            {
                chFilename = chFilename.arg(QString("0%1").arg(i));
            } else
            {
                chFilename = chFilename.arg(i);
            }
            QString channelDataStr = QString("%1 [%2] %3").arg(phaseData->timestamp).arg(phaseData->frameId).arg(phaseData->channelDataStr.at(i-1));

            QLogUtil::writeChannelDataLogByDate(date, chFilename, channelDataStr);

            QJsonObject jsonObj = phaseData->toJSON(i - 1);
            jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID);
            jsonObj.insert("master", SettingConfig::getInstance().MASTER);
            jsonObj.insert("deviceId", deviceId);
            messageArray.append(jsonObj);
        }
    }

    // 3. 输出到中间件，执行后续处理过程
    if (SettingConfig::getInstance().NEED_KAFKA == 1)
    {
        kafkaUtil.produceMessage(QString(QJsonDocument(messageArray).toJson(QJsonDocument::Compact)));

        QJsonObject statusObj = phaseData->toStatusJSON();
        statusObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID);
        statusObj.insert("deviceId", deviceId);
        statusObj.insert("master", SettingConfig::getInstance().MASTER);
        kafkaUtil.produceMessage(SettingConfig::getInstance().KAFKA_STATUS_TOPIC, QString(QJsonDocument(statusObj).toJson(QJsonDocument::Compact)));
    }

    // 4. 在界面上简单显示相差数据结果
    emit this->sendDataToDraw(phaseData);
}
