#include "FreqReplicator.h"
#include "DeviceHubWindow.h"
#include <iostream>
#include <QDateTime>

FreqReplicator::FreqReplicator(QObject *parent) : DeviceBase(parent)
{
    this->devType = "10";
    connect(&this->serialUtil, &QSerialPortUtil::dataRecieved,
            this, &FreqReplicator::dataReceivedHandler);
    connect(&this->serialUtilB, &QSerialPortUtil::dataRecieved,
            this, &FreqReplicator::dataBReceivedHandler);

    connect(this, &FreqReplicator::sendDataToDraw,
            ((DeviceHubWindow *)this->parent())->freqRepForm, &FreqReplicatorForm::drawDeviceFrameOnForm);

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

    this->protocol = DeviceProtocolBase::deviceProtocolFactory(devType);
}

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

void FreqReplicator::mockReceivData()
{
    QByteArray buffer;

    // 频率信号放大器
//    buffer.append(QByteUtil::hexStringToBytes("AA550015010001000101010101010101010101010101010101EB"));
//    buffer.append(QByteUtil::hexStringToBytes("AA550015020001000101010101010101010101010101010101E8"));
    buffer.append(QByteUtil::hexStringToBytes("AA55000B0100010101010101010101F4AA55000B0200010101010101010101F7"));

    this->dataReceivedHandler(buffer);
}

void FreqReplicator::dataReceivedHandler(QByteArray data)
{
    this->dataBuff.append(data);
    QList<QByteArray> frameList = protocol->extractFrameList(this->dataBuff);
    if (frameList.size() > 0)
    {
        this->dataBuff.clear();
        frameParse(frameList);
    }
}

void FreqReplicator::dataBReceivedHandler(QByteArray data)
{
    this->dataBuffB.append(data);
    QList<QByteArray> frameListB = protocol->extractFrameList(this->dataBuffB);
    if (frameListB.size() > 0)
    {
        this->dataBuffB.clear();
        frameParse(frameListB);
    }
}

void FreqReplicator::frameParse(QList<QByteArray> frameList)
{
    for (int i = 0; i < frameList.size(); i++)
    {
        QByteArray frameByte = frameList.at(i);

        int frameType = protocol->checkFrame(frameByte);
        DeviceFrameBaseDto * frameDto = protocol->frameFactory(frameType);
        if (frameDto != nullptr)
        {
            // ★解析成数据对象
            bool parse = protocol->parseDeviceFrameData(frameByte, frameDto, frameType);

            // 解析成功
            if (parse == true)
            {
                QDateTime now = QDateTime::currentDateTime();
                frameDto->timestamp = now.toString("yyyy-MM-dd HH:mm:ss.zzz");
                frameDto->milisecond = now.toMSecsSinceEpoch();
                frameDto->rawFrame = frameByte;

                frameDto->devCode = devCode;

                this->afterFrameParse(frameDto);
            }

            // 在此处释放内存，不影响后续显示
            // 不在此处释放内存则会导致内存持续增加
            // 具体原因不明
            delete frameDto;
        }
    }
}
void FreqReplicator::afterFrameParse(DeviceFrameBaseDto * frameDto)
{
//    std::cout << QByteUtil::binToHexString(frameDto->rawFrame).toStdString() << std::endl;

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

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

    // 2. 解析后的json数据
    QString frameFilename = "frame_" + devCode + ".log";
    QString frameContent = frameDto->timestamp + " [recv] " + QJsonDocument(frameDto->toJSON()).toJson(QJsonDocument::Compact);
    QLogUtil::writeChannelDataLogByDate(date, frameFilename, frameContent);

    // 3. 输出到中间件，执行后续处理过程
    if (SettingConfig::getInstance().NEED_KAFKA == 1)
    {
        QJsonObject jsonObj = frameDto->toJSON();
        jsonObj.insert("clientId", SettingConfig::getInstance().CLIENT_ID);
        jsonObj.insert("deviceId", deviceId);
        kafkaProducer.produceMessage(QString(QJsonDocument(jsonObj).toJson(QJsonDocument::Compact)));
    }

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