#include "serialport.h"
#include <QSerialPortInfo>
#include "logger.h"

SerialPort::SerialPort(QObject *parent)
    : QObject{parent}
{
    QList<QSerialPortInfo> serialPorts = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &info : serialPorts) {
        LOG_INFO("Name         : {}", info.portName().toUtf8().data());
        LOG_INFO("Description  : {}", info.description().toUtf8().data());
        LOG_INFO("Manufacturer : {}", info.manufacturer().toUtf8().data());
        LOG_INFO("Serial Number: {}", info.serialNumber().toUtf8().data());
        LOG_INFO("Location     : {}", info.systemLocation().toUtf8().data());
        LOG_INFO("Vendor ID    : {}", info.vendorIdentifier());
        LOG_INFO("Product ID   : {}", info.productIdentifier());
        LOG_INFO("-----------------------------------");
    }

    m_serialPort.setPortName("/dev/ttyS9"); 
    m_serialPort.setBaudRate(QSerialPort::Baud115200);
    m_serialPort.setDataBits(QSerialPort::Data8);
    m_serialPort.setParity(QSerialPort::NoParity);
    m_serialPort.setStopBits(QSerialPort::OneStop);
    m_serialPort.setFlowControl(QSerialPort::NoFlowControl);

    if (!m_serialPort.open(QIODevice::ReadOnly)) {
        LOG_ERROR("failed to open port:", m_serialPort.errorString().toUtf8().data());
        return;
    }

    ringbuffer_init(&m_ringbuffer, 64);
    memset(m_ringbuffer.data, 0 , 64);

    connect(&m_serialPort, &QSerialPort::readyRead, [this](){
        QByteArray byteArray = m_serialPort.readAll();
        LOG_DEBUG("serial received: {}", byteArray.toHex().data());  // 或直接输出 data
        ringbuffer_append(&m_ringbuffer, (data_t*)byteArray.data(), byteArray.size());
        int ret;
        int frameSize;
        data_t head[2];
        data_t data;
        data_t buffer[12];
        data_t checkSum;
        while(1)
        {
            if(m_ringbuffer.buffer_size < 12)
                break;
        
            if(0 == ringbuffer_data(m_ringbuffer, &head[0], 0) && 0 == ringbuffer_data(m_ringbuffer, &head[1], 1))
            {
                if(0xAA == head[0] && 0x55 == head[1])
                {
                    ringbuffer_data(m_ringbuffer, &data, 2);
                    frameSize = data;
                    if(data != 12)
                    {
                        LOG_ERROR("frame size error");
                        ringbuffer_popup(&m_ringbuffer, 2);
                    }
                    else
                    {
                        int size = ringbuffer_read(m_ringbuffer, buffer, frameSize);
                        if(size == frameSize)
                        {
                            checkSum = 0x00;
                            for(int i = 0; i < size - 3; i++)
                            {
                                checkSum += buffer[i];
                            }

                            if(buffer[3] != 0x11)
                            {
                                LOG_ERROR("cmd code error");
                                ringbuffer_popup(&m_ringbuffer, 2);
                                continue;
                            }

                            if(checkSum != buffer[size - 3])
                            {
                                LOG_ERROR("check sum error");
                                ringbuffer_popup(&m_ringbuffer, 2);
                                continue;
                            }

                            if(0xBB != buffer[size - 2] || 0x66 != buffer[size - 1])
                            {
                                LOG_ERROR("tail error");
                                ringbuffer_popup(&m_ringbuffer, 2);
                                continue;
                            }

                            if(buffer[4] == 0x00) {
                                emit pageSwitch(-1);
                            }
                            else if(buffer[4] == 0x01) {
                                emit pageSwitch();
                            }

                            LOG_DEBUG("key state                    : {:x}", buffer[4]);
                            LOG_DEBUG("heating state                : {:x}", buffer[5]);
                            LOG_DEBUG("screen temperature           : {}", static_cast<int8_t>(buffer[6]));
                            LOG_DEBUG("Interface onboard temperature: {}", static_cast<int8_t>(buffer[7]));
                            ringbuffer_popup(&m_ringbuffer, size);
                        }
                    }
                }
                else
                {
                    ringbuffer_popup(&m_ringbuffer, 1);
                }
            }
        }

    });
}

SerialPort::~SerialPort()
{

}