#ifndef M3KTE_H
#define M3KTE_H

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

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

#include <QModbusTcpClient>
#include <QModbusRtuSerialMaster>

#include <QHBoxLayout>
#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; class DebugTerminalDialog;}
QT_END_NAMESPACE

#define LOCAL_STATE_POLL    0
#define LOCAL_STATE_WARN    1
#define LOCAL_STATE_ERR     2

class SettingsDialog;
class DebugTerminalDialog;
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, int status);
    void applySettingsFromScan(QModbusReply *reply);
    void multipleRegWrite();
    void multipleRegSend();
    void writeSingleCoil(int boardId, int coilAddress, bool value);
    void writeSingleRegister(int boardId, int regAddress, quint16 value);
    bool autoBaudRateScan();
    void selectPositionOnTree(unsigned index);
signals:
    void successAtCheckBoards();
    void errorAtCheckBoards();
    void boardReading(int boardID);
private slots:
    void clearLogger();
    void logError(const QString &errorPlace, const QString &errorString, unsigned errorCount, const QString &description);
    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 checkBoards();
    void onSpeedUpdate();
    void revertToOldSpeedAndRestart();
    void onParityUpdate();
    void boardScan(unsigned boardID);
public:
    M3KTE(QWidget *parent = nullptr);
    ~M3KTE();
    QModbusClient* getModbusDevice() const { return modbusDevice; }
    QModbusReply* readSingleCoil(int boardID, int coilAddress);
private:
    Ui::M3KTE *ui;
    QTableWidget *loggerTable = nullptr;
    int CurrentConnectedDevice = 0;
    QProgressBar *m_ProgressBar[320];
    QPushButton *ThePhantomMenace[320];
    QModbusReply *lastRequest = nullptr;
    QModbusClient *modbusDevice = nullptr;
    DeviceSettingsDialog *m_deviceSettingsDialog = nullptr;
    DebugTerminalDialog *m_debugTerminalDialog = nullptr;
    SettingsDialog *m_settingsDialog = nullptr;
    MultipleSettings *m_regMultipleSettings = nullptr;
    ScanBoard *m_scanBoard = nullptr;
    LineRinger *m_lineRinger = nullptr;
    QGroupBox *Boards_Fields[4];
    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;
        QLabel *localError = nullptr;
        QCheckBox *localState[3] = {nullptr, nullptr, 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;
    };
};
#endif // M3KTE_H
