#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include <binary_protocol.h>
#include <QLabel>
#include <QTimer>
#include <QProgressBar>
#include <QFile>
#include <QByteArray>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QLineEdit>
#include <QListWidgetItem>
#include <QtNetwork>
#include "config.h"
#include <QTcpServer>
#include <QTcpSocket>

#define MAX_ARGS 10
#define FIRMWARE_PART_SIZE  256
#define SEARCH_TIMEOUT  100

typedef enum {
    WIFI_MODE = 0x00,
    WIFI_AUTH,
    WIFI_CHANNEL,
    WIFI_SID,
    WIFI_PASSWORD,
    DHCP_CLIENT,
    NET_ADDR,
    NET_NETMASK,
    NET_GATEWAY,
    NET_DNS,
    WEB_ADMIN,
    WEB_PASSWORD
} cmd_set_network_cfg;

typedef enum {
    CMD_ACK = 0x00,
    CMD_DUMMY_COMMAND,
    CMD_GET_TAG_COUNT,
    CMD_GET_UID,
    CMD_ACTIVATE_TAG,
    CMD_HALT,
    CMD_SET_POLLING,
    CMD_SET_KEY,
    CMD_SAVE_KEYS,
    CMD_SET_NET_CFG,
    CMD_REBOOT,
    CMD_GET_VERSION,
    CMD_UART_PASSTHRU,
    CMD_SLEEP,
    CMD_GPIO,
    CMD_ANTENNA,
    CMD_BT_PIN,
    CMD_FACTORY_RESET,
    CMD_SET_PROTOCOL, //nto implemented

    //mifare clasics commands
    CMD_MF_READ_BLOCK = 0x20,
    CMD_MF_WRITE_BLOCK,
    CMD_MF_READ_VALUE,
    CMD_MF_WRITE_VALUE,
    CMD_MF_INCREMENT,
    CMD_MF_TRANSFER,
    CMD_MF_RESTORE,
    CMD_MF_TRANSFER_RESTORE,

    //mifare ultralight
    CMD_MFU_READ_PAGE = 0x40,
    CMD_MFU_WRITE_PAGE,
    CMD_MFU_GET_VERSION,
    CMD_MFU_READ_SIG,
    CMD_MFU_WRITE_SIG,
    CMD_MFU_LOCK_SIG,
    CMD_MFU_READ_COUNTER,
    CMD_MFU_INCREMENT_COUNTER,
    CMD_MFU_PASSWD_AUTH,
    CMD_MFUC_AUTHENTICATE,
    CMD_MFU_CHECKEVENT,

    CMD_MFDF_GET_VERSION = 0x60,
    CMD_MFDF_SELECT_APP,
    CMD_MFDF_APP_IDS,
    CMD_MFDF_FILE_IDS,
    CMD_MFDF_AUTH,
    CMD_MFDF_AUTH_ISO,
    CMD_MFDF_AUTH_AES,
    CMD_MFDF_CREATE_APP,
    CMD_MFDF_DELETE_APP,
    CMD_MFDF_CHANGE_KEY,
    CMD_MFDF_GET_KEY_SETTINGS,
    CMD_MFDF_CHANGE_KEY_SETTINGS,
    CMD_MFDF_CREATE_DATA_FILE,
    CMD_MFDF_WRITE_DATA,
    CMD_MFDF_READ_DATA,
    CMD_MFDF_CREATE_VALUE_FILE,
    CMD_MFDF_GET_VALUE,
    CMD_MFDF_CREDIT,
    CMD_MFDF_LIMITED_CREDIT,
    CMD_MFDF_DEBIT,
    CMD_MFDF_CREATE_RECORD_FILE,
    CMD_MFDF_WRITE_RECORD,
    CMD_MFDF_READ_RECORD,
    CMD_MFDF_CLEAR_RECORDS,
    CMD_MFDF_DELETE_FILE,
    CMD_MFDF_GET_FREEMEM,
    CMD_MFDF_FORMAT,
    CMD_MFDF_COMMIT_TRANSACTION,
    CMD_MFDF_ABORT_TRANSACTION,

    CMD_ICODE_INVENTORY_START = 0x90,
    CMD_ICODE_INVENTORY_NEXT,
    CMD_ICODE_STAY_QUIET,
    CMD_ICODE_READ_BLOCK,
    CMD_ICODE_WRITE_BLOCK,
    CMD_ICODE_LOCK_BLOCK,
    CMD_ICODE_WRITE_AFI,
    CMD_ICODE_LOCK_AFI,
    CMD_ICODE_WRITE_DSFID,
    CMD_ICODE_LOCK_DSFID,
    CMD_ICODE_GET_SYSTEM_INFORMATION,
    CMD_ICODE_GET_MULTIPLE_BSS,
    CMD_ICODE_PASSWORD_PROTECT_AFI,
    CMD_ICODE_READ_EPC,
    CMD_ICODE_GET_NXP_SYSTEM_INFORMATION,
    CMD_ICODE_GET_RANDOM_NUMBER,
    CMD_ICODE_SET_PASSWORD,
    CMD_ICODE_WRITE_PASSWORD,
    CMD_ICODE_LOCK_PASSWORD,
    CMD_ICODE_PROTECT_PAGE,
    CMD_ICODE_LOCK_PAGE_PROTECTION,
    CMD_ICODE_GET_MULTIPLE_BPS,
    CMD_ICODE_DESTROY,
    CMD_ICODE_ENABLE_PRIVACY,
    CMD_ICODE_ENABLE_64BIT_PASSWORD,
    CMD_ICODE_READ_SIGNATURE,
    CMD_ICODE_READ_CONFIG,
    CMD_ICODE_WRITE_CONFIG,
    CMD_ICODE_PICK_RANDOM_ID,

    CMD_OTA_BEGIN 	= 0xF0,
    CMD_OTA_FRAME,
    CMD_OTA_FINISH,

    CMD_ASYNC 	= 0xFE,
    CMD_ERROR	= 0xFF,
} i2c_coommands_t;

typedef enum {
    TIMER_STATE_IDLE,
    TIMER_WAIT4VERSION,
    TIMER_WAIT4SEARCH_DEVICES,
    TIMER_FIRMWARE_LOADING,
    TIMER_READING_NETWORK,
    TIMER_WRITING_NETWORK,
} timerState_t;

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    Config *config;
    void reloadFavs();
    void loadCommands(int state);
private slots:
    void logd(QString msg);
    void protoLog(QByteArray msg, QString prefix);
    void protoLogRaw(QByteArray msg, QString prefix);
    void handleSerialDataReady();
    void handleSerialDataError(QSerialPort::SerialPortError serialPortError);

    void binaryProtocolFrameComplete(uint8_t *buff, size_t len);
    void binaryProtocolWrite(uint8_t *buff, size_t len);
    void binaryProtocolFrameTimeout();
    void binaryProtocolFrameError();

    void oneShotTimeout(void);
    void pollingTimeout(void);
    void on_btSerialConnect_clicked();
    void on_btFlashFirmware_clicked();
    void on_btRefresComPorts_clicked();
    void on_btClearLogs_clicked();
    void on_btScanRs485_clicked();
    void on_cbDetectedDevices_currentIndexChanged(const QString &arg1);
    void on_btCommnadExecute_clicked();
    void on_lvCommands_currentRowChanged(int currentRow);
    void on_lvCommands_itemDoubleClicked(QListWidgetItem *item);
    void on_btAddFavCommand_clicked();
    void on_lvFavCommands_itemDoubleClicked(QListWidgetItem *item);
    void on_btDeleteFavCommand_clicked();
    void addNewFavCommand(int idx, QString name, QString hex);
    void on_btFavDown_clicked();
    void on_btFavUp_clicked();
    void on_btEditFavCommand_clicked();
    void on_cbDetectedDevices_activated(const QString &arg1);
    void on_btShowLegend_clicked();
    void on_btReadNetwork_clicked();
    void on_btWriteNetwork_clicked();
    void on_cbAddressType_currentIndexChanged(int index);

    void on_cbWifiMode_currentIndexChanged(int index);

    void on_tabs_currentChanged(int index);

    void on_btRestartDevice_clicked();
    //network
    void udpReceive();

    void onSocketStateChanged(QAbstractSocket::SocketState socketState);
    void onReadyRead();
    void tcpClientError(QAbstractSocket::SocketError socketError);
    void connectToHost(QString address, int port);
    void disconnectHost();
    void on_cbSaveToFile_stateChanged(int arg1);

    void on_btSelectOutputXlsFile_clicked();
    void on_btStartPolling_clicked();

    void on_btStopPolling_clicked();

    void on_btNetworkConnect_clicked();

    void on_btNetworkRefresh_clicked();

    void on_tabWidget_currentChanged(int index);

private:
    Ui::MainWindow *ui;
    QSerialPort serialPort;
    BinaryProtocol binaryProtocol;
    QByteArray lastReceivedFrame;

    uint8_t searchAddress;

    QLabel *hardwareLabel;
    QLabel *statusLabel;
    QProgressBar *progressBar;

    QTimer *oneShotTimer;
    timerState_t oneShotTimerState;

    QTimer *pollingTimer;

    QUdpSocket *udpSocket;

    QJsonArray jsonCommandsArray;
    QLabel *argsLabel[MAX_ARGS];
    QLineEdit *argsEdit[MAX_ARGS];
    QString lastValue[MAX_ARGS];

    QString getCommandName(int cmdValue);

    QTcpSocket *clientSocket;
    bool tcpClientConnected;


    void serialPortClose(void);
    void serialPortOpen(void);
    void serialPortRefreshList(void);
    void requestVersion(void);
    void requestHardwareVersion(void);
    void scanNext(void);
    void firmwareFlashStart(void);
    void firmwareFlashFrame(void);
    void firmwareFlashEnd(void);
    QString byte2hexstring(uint8_t value);
    void storeTag2File(QString uid);
    QByteArray firmwareBuff;
    int firmwarePos;
    QString firmwareFileName;
    int retry_count;
};
#endif // MAINWINDOW_H
