#include <QDebug>
#include <QDataStream>
#include <stddef.h>

#include "dataparser.h"
#include "defines.h"
#include "global.h"
#include "logger.h"

namespace DataParser
{
bool commonDataParser(const QByteArray &ba, CommonData &cd)
{
    const char *charArray = ba.data();

    // 判断前两个字节是否为 0xA5 和 0x5A (小端格式)
    if (static_cast<unsigned char>(charArray[0]) == 0xA5 &&
            static_cast<unsigned char>(charArray[1]) == 0x5A)
    {
        //                std::cout << "前两个字节是 0x5AA5 (小端)" << std::endl;
    }
    else
    {
        //        std::cout << "前两个字节不是 0x5AA5 (小端)" << std::endl;
        qDebug() << "header failed.";
        return false;
    }

    if (static_cast<unsigned char>(charArray[3]) != 0x83)
    {
        qDebug() << "mark failed.";
        return false;
    }

    memcpy(&cd, charArray + 6, sizeof(CommonData));

    return true;
}



QByteArray setExperimentInfo(const QVector<Phase> &vtr,const QByteArray initBa)
{
    //    const int phaseLength = sizeof(Phase);
    const int phaseLength = PHASE_BYTE_SIZE;

    const int phaseArrayLength = vtr.size() * phaseLength;
    char phaseArray[300] = {};
    int offset = 0;

    for (const Phase &phase : vtr)
    {
        memcpy(phaseArray + offset, &phase, sizeof(Phase));
        offset += phaseLength;
    }

    //
    //    int totalDataLength = 0;
    char totalData[300] = {};

    u16 header = 0x5aa5;
    memcpy(totalData, (char *)&header, sizeof(u16));

    // command + addr + data + crc
    totalData[2] = 1 + 2 + phaseArrayLength + 2 + 2;

    totalData[3] = 0x82;

    u16 address = 0x0050;
    memcpy(totalData + 4, (char *)&address, sizeof(u16));

    memcpy(totalData + 6, phaseArray, phaseArrayLength);

    memcpy(totalData + 6 + phaseArrayLength,initBa.data(),2);

    //
    char data[300] = {};

    data[0] = 0x82;

    //    u16 address = 0x0050;
    memcpy(data + 1, (char *)&address, sizeof(u16));

    memcpy(data + 3, phaseArray, phaseArrayLength);
    // initial data
    memcpy(data + 3 + phaseArrayLength,initBa.data(),2);

    u16 crc = modbusCRC16((u8 *)data, 3 + phaseArrayLength + 2);
    //
    memcpy(totalData + 6 + phaseArrayLength + 2, (char *)&crc, sizeof(u16));

    // header + phase  data + initial data + crc.
    return QByteArray(totalData, 6 + phaseArrayLength + 2 + 2);
}

QByteArray setDeviceStartStop(const DeviceStartMode mode)
{
#if 1
    SerialPortProtocol spp;
    spp.head = FRANE_HEAD;
    spp.len = 1 + 2 + 1 + 2;
    spp.cmd = WRITE_CMD;
    spp.addr = 0x002c;
    spp.data_buf[0] = mode;

    int sppValidLength = 6 + 1;

    u8 *dataPtr = (u8 *)&spp;
    u16 crc = modbusCRC16((u8 *)(dataPtr + 3), 4);

    return QByteArray((char *)&spp, sppValidLength) +
            QByteArray((char *)&crc, 2);
#endif

#if 0
    char data[300] = {};
    // header
    u16 header = 0x5aa5;
    memcpy(data, (char *)&header, sizeof(u16));

    // length
    data[2] = 1 + 2 + 1 + 2;

    // commond
    data[3] = 0x82;

    //address
    u16 address = 0x002C;
    memcpy(data + 4, (char *)&address, sizeof(u16));

    data[6] = mode;

    //crc
    u16 crc = modbusCRC16((u8 *)(data + 3), 4);
    memcpy(data + 7, (char *)&crc, sizeof(u16));

    int length = 9;

    return QByteArray(data,length);
#endif
}

void experimentalStateSwitching(const CommonData &cd)
{
    // Switch the software mode accord to the serial port data.
    switch(cd.run_type){
    case DeviceRunStatus::Heat:
    case DeviceRunStatus::ConstantTemp:
        Global::_mode = Global::Mode::Experiment;
        break;
    case DeviceRunStatus::Idle:
    case DeviceRunStatus::Cooling:
        Global::_mode = Global::Mode::Analysis;

        break;
    default:break;
    }

#if 0
        logde<<"phase:"<<(int)cd.current_phase;
        logde<<"run type:"<<(int)cd.run_type;
        logde<<"software mode:"<<Global::_mode;
#endif
}

unsigned short modbusCRC16(unsigned char *data, unsigned short length)
{
    unsigned short crc = 0xFFFF;
    unsigned char i;
    for (unsigned short j = 0; j < length; j++)
    {
        crc ^= (unsigned short)data[j];
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x0001)
            {
                crc = (crc >> 1) ^ 0xA001;
            }
            else
            {
                crc = crc >> 1;
            }
        }
    }
    // CRC结果低字节在前，高字节在后
    return crc;
}

QByteArray inquirePhaseInfo()
{
    SerialPortProtocol spp;
    spp.head = FRANE_HEAD;
    spp.cmd = READ_CMD;
    spp.addr = 0x0050;
    spp.len = 6;
    //
    spp.data_buf[0] = PHASE_BYTE_SIZE * 6 + 2;
    //
    u8 *dataPtr = (u8 *)&spp;
    u16 crc = modbusCRC16((u8 *)(dataPtr + 3), 4);
    //
    int sppValidLength = 6 + 1;
    return QByteArray((char *)&spp, sppValidLength) +
            QByteArray((char *)&crc, 2);
}




};
