#ifndef TCPSERVERTHREAD_H
#define TCPSERVERTHREAD_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QThreadPool>
#include <QRunnable>
#include <QtEndian>
#include <QTimer>

#include "DataTypeDef.h"

class ClientHandler : public QObject
{
    Q_OBJECT
public:

    ClientHandler(qintptr socketDescriptor);
    ~ClientHandler();

    bool sendData(const uint8_t &cmd, const QByteArray& info);

private:
    // 解析 CCU 向 TCU 发送的数据
    void parseClientMsg(const QByteArray& data);
    void parseChargeGunBasicInfo(const QByteArray& data);
    void parseChargeGunChargeInfo(const QByteArray& data);
    void parseChargeGunStart(const QByteArray& data);
    void parseChargeGunStop(const QByteArray& data);

    // 具体属性分析
    void parseGunError(const uint32_t& gun_error, const uint32_t& gun_id);
    void parseGunState(const uint32_t& gun_state, const uint32_t& gun_id);
    void parseGunType(const uint32_t& gun_type, const uint32_t& gun_id);

    void refreshBasicInfo(const BASIC_INFO& info);
    void refreshChargingInfo(const CHARGING_INFO& info);

    void initErrorDescriptions();
    void initStateDescriptions();
    void initTypeDescriptions();

    QMap<uint8_t, QString> parseCodeBits(uint32_t code, const QMap<uint8_t, QString>& bitDescriptions);

signals:
    void disconnected();
    void chargeGunCtlReply(const int& result);
    void gunCtlReplyTimeout();

private slots:
    void slotInit();
    void onReadyRead();
    void onDisconnected();
    void onError(QAbstractSocket::SocketError socketError);

private:
    qintptr m_socketDescriptor;
    QTcpSocket* m_socket = nullptr;
    QThread* m_thread = nullptr;

    QMap<uint8_t, QString> m_errorDescriptions;
    QMap<uint8_t, QString> m_stateDescriptions;
    QMap<uint8_t, QString> m_typeDescriptions;
};

class TcpServerThread : public QTcpServer
{
    Q_OBJECT
public:
    static TcpServerThread* instance();
    explicit TcpServerThread(QTcpServer *parent = nullptr);
    ~TcpServerThread();

    uint8_t init();

    bool sendData(const uint8_t& cmd, const QByteArray& info);

protected:
    void incomingConnection(qintptr socketDescriptor) override;

signals:
    void chargeGunCtlReply(const int& result);
    void gunCtlReplyTimeout();

private:
    ClientHandler* m_clientHandler = nullptr;
};

#endif // TCPSERVERTHREAD_H
