#ifndef UPDATE_H_INCLUDED
#define UPDATE_H_INCLUDED

#include <QObject>
#include <QString>
#include <QFile>
#include <QDir>
#include <QByteArray>
#include <QProcess>
#include <QPluginLoader>
#include <QDateTime>
#include <cmath>

#include <initializer_list>

#include <DeviceController/interfaces.h>

#ifdef PTU5
#define SERIAL_PORT "ttymxc2"
#define BAUDRATE 115200
#else
#define SERIAL_PORT "ttyUSB0"
#define BAUDRATE 115200
#endif

class QSerialPort;
class Update : public QObject {
    Q_OBJECT

    QString m_dcFileName{};
    hwinf *m_hw = nullptr;
    bool m_sys_areDCdataValid{};
    bool m_debug;
    bool m_noaction;

    static QPluginLoader pluginLoader;

    QDateTime m_start;
    QString nextTimePoint() const {
        float const secs = m_start.msecsTo(QDateTime::currentDateTime()) / 1000.0;
        return QStringLiteral("+%1s").arg(secs, 7, 'f', 2, QChar('0'));
    }

public:
    enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
    enum class Result {SUCCESS=0, PLUGIN_LOAD_ERROR};

    static hwinf *loadDCPlugin(QString const &libCA = "/usr/lib/libCAslave.so");
    static bool unloadDCPlugin();
    static QStringList split(QString line, QChar sep = ',');

    explicit Update(QString const &dcBinFile, QString const &libCA, bool debug, bool noaction);
    virtual ~Update() override;

    int run();
    static QString dcVersion(QString const &dcBinFile);

private:
    DownloadResult sendStatus(int ret) const;
    DownloadResult sendNextAddress(int bNum) const;
    DownloadResult sendNextDataBlock(QByteArray const &binary, int bNum) const;
    bool startBootloader() const;
    bool stopBootloader() const;
    QByteArray loadBinaryDCFile(QString const &dcFilename) const;
    bool resetDeviceController() const;
    DownloadResult dcDownloadBinary(QByteArray const &b) const;

    QString m_fileToDownload;
    uint16_t m_totalBlocks = 0;
/*
private:
    static QString jsonType(enum FileTypeJson type);
    bool openSerial(int br, QString baudrate, QString comPort) const;
    void closeSerial() const;
    bool isSerialOpen() const;
    bool resetDeviceController() const;
    QByteArray loadBinaryDCFile(QString filename) const;
    bool downloadBinaryToDC(QString const &bFile) const;
    bool updateBinary(QString const &fileToSendToDC);
    QStringList getDcSoftAndHardWareVersion();
    QString getFileVersion(QString const& jsonFile);

private slots:
    void readyReadStandardOutput();
    void readyReadStandardError();
    void finished(int exitCode, QProcess::ExitStatus exitStatus);
    void onReportDCDownloadStatus(QString const &status);
    void onReportDCDownloadSuccess(QString const &msg);
    void onReportDCDownloadFailure(QString const &errorMsg);
*/
};
#endif // UPDATE_H_INCLUDED