#ifndef M3KTE_H
#define M3KTE_H

#include <QMainWindow>
#include <QModbusDataUnit>
#include <qprogressbar.h>

#include <QtSerialBus/QModbusDataUnit>
#include "writeregistermodel.h"
#include "devicesettingsdialog.h"
#include "multiplesettings.h"
#include "scanboard.h"
#include "lineringer.h"

#include <QModbusTcpClient>
#include <QModbusRtuSerialMaster>

#include <QTimer>
#include <QMessageBox>
#include <QProgressDialog>
#include <QErrorMessage>
#include <QPushButton>
#include <QGroupBox>
#include <QTableWidget>
#include <QTime>
#include <QElapsedTimer>

#include <QtSerialBus/qtserialbusglobal.h>

#if QT_CONFIG(modbus_serialport)
#include <QSerialPort>
#endif

#define MODBUS_REQUEST_PROTOCOL_INFO_LENGTH 8

extern "C" __declspec(dllexport) QWidget* init(QWidget *parent);

QT_BEGIN_NAMESPACE
namespace Ui { class M3KTE; class SettingsDialog;}
QT_END_NAMESPACE

class SettingsDialog;
class WriteRegisterModel;

class M3KTE : public QMainWindow
{
    Q_OBJECT
private:
    void initActions();
    QModbusDataUnit readRequest() const;
    QModbusDataUnit writeRequest() const;
    void changeTable(int board, int tabletype);
    bool event(QEvent* event);
    bool pingNetworkDevices();
    void beginScanBoards();
    void stopScanBoard();
    void displayResultOfScan(QModbusReply *reply, int boardID);
    void applySettingsFromScan(QModbusReply *reply);

    void multipleRegWrite();
    void multipleRegSend();

    bool autoBaudRateScan();

    void selectPositionOnTree(unsigned index);
private slots:

    void slotmultipleRegWrite();
    void slotmultipleRegWriteAndSend();

    void onConnectClicked();

    void onReadButtonClicked();
    void onReadReady();

    void checkAdrChange(QModbusReply *reply, unsigned boardNum);

    void onWriteButtonClicked();
    void onSelectedBoardChanged(int index);
    void onWriteTableChanged(int index);

    void onSpeedUpdate();
    void onParityUpdate();

    void boardScan(unsigned boardID);

    void handleSpeedChangeReply(QModbusReply *reply, int boardIndex);
    void onAllSpeedChangeRepliesReceived();
    void revertToOldSpeedAndRestart();

public:
    M3KTE(QWidget *parent = nullptr);
    ~M3KTE();

private:
    Ui::M3KTE *ui;
    QTableWidget *loggerTable = nullptr;
    int CurrentConnectedDevice = 0;
    //int DeviceOnNetwork[4];
    QProgressBar *m_ProgressBar[320];
    QPushButton *ThePhantomMenace[320];
    QModbusReply *lastRequest = nullptr;
    QModbusClient *modbusDevice = nullptr;
    DeviceSettingsDialog *m_deviceSettingsDialog = nullptr;
    SettingsDialog *m_settingsDialog = nullptr;
    MultipleSettings *m_regMultipleSettings = nullptr;
    ScanBoard *m_scanBoard = nullptr;

    LineRinger *m_lineRinger = nullptr;
    QGroupBox *Boards_Fields[4];
    //WriteRegisterModel *writeModel = nullptr;

    struct StatusM3KTE{
        bool Warnings[4];
        bool Accidents[4];
    }statusM3KTE;

    unsigned error_terminal;

    struct BoardModbusRegisters
    {
        bool isActive = false;
        bool pollIsActive = true;

        int adr;
        int _tmp_adr;

        bool coil[85];
        unsigned HR[170];

        unsigned error_W = 0;
        unsigned error_A = 0;
        unsigned error_modbus = 0;
        unsigned error_baud_change = 0;
        unsigned error_parity_change = 0;
        unsigned error_RX = 0;
        unsigned error_TX = 0;
        unsigned error_adr_change = 0;
        unsigned error_cmd_change = 0;

        QLabel *timerData = nullptr;
        QLabel *timerStatus = nullptr;

        WriteRegisterModel *ModbusModelCoil;
        WriteRegisterModel *ModbusModelHoldingReg;
        QTimer *boardScanners;
        bool isScan = false;

        QElapsedTimer timerToStatusResponse;
        QElapsedTimer timerToDataResponse;
    }Boards[4];

    union statusreg
    {
        struct parsingFields
        {
            unsigned accident:1;
            unsigned warning:1;
            unsigned poll_allowed:1;
            unsigned mzkte_status:2;
            unsigned reserv:3;
            unsigned mzkte_error:8;
        }ParsingReg;
        unsigned AllReg:16;
    };

    // Структура для отслеживания состояния запроса смены скорости
    struct SpeedChangeRequest {
        int boardIndex;
        bool errorOccurred = false;
        bool finished = false;
        bool confirmationReceived = false;
    };
    QVector<SpeedChangeRequest> speedChangeRequests;
    int pendingSpeedChangeRequestsCount = 0;
    int pendingConfirmationsCount = 0;
    unsigned tmp_speed = 0;
};
#endif // M3KTE_H
