#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 <initializer_list>

#include <DeviceController/interfaces.h>

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

class Update : public QObject {
    Q_OBJECT

    hwinf *m_hw = nullptr;
    char const *m_serialInterface;
    char const *m_baudrate;
    QString m_customerRepository;
    QString m_customerNrStr;
    QString m_branchName;
    QString m_pluginName;
    QString m_workingDir;
    bool m_maintenanceMode;
    bool m_dryRun;
    bool m_sys_areDCdataValid;

    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'));
    }

    static qint64 c_ppid;

public:
    enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
    enum class FileTypeJson {CONFIG=1, DEVICE=2, CASH=3, SERIAL=4, TIME=5, PRINTER=6};

    static hwinf *loadDCPlugin(QDir const &plugInDir, QString const &fn);
    static bool unloadDCPlugin();
    static QStringList split(QString line, QChar sep = ',');

    static qint64 ppid() { return c_ppid; }
    static void setPPid(qint64 ppid) { c_ppid = ppid; }

    explicit Update(QString customerRepository,
                    QString customerNrStr,
                    QString branchName,
                    QString plugInDir,
                    QString pluginName,
                    QString workingDir,
                    bool dryRun = false,
                    QObject *parent = nullptr,
                    char const *serialInterface = SERIAL_PORT,
                    char const *baudrate = "115200");

    virtual ~Update() override;

    bool doUpdate(QStringList const &jsonFilesToDownload, bool usbStickDetected = false);
    bool doUpdate();

    bool updatePrinterTemplate(int templateIdx, QString fname) const;
    bool updateConfig(QString jsFileToSendToDC);
    bool updateCashConf(QString jsFileToSendToDC);
    bool updateDeviceConf(QString jsFileToSendToDC);

    bool downloadJson(enum FileTypeJson type, int templateIdx,
                      QString jsFileToSendToDC) const;


    QString getFileVersion(QString const& jsonFileName);
    bool checkJsonVersions(QStringList const& jsonFileNames =
                            QStringList(
                                QList(
                                    std::initializer_list<QString>{
                                        QString("etc/psa_config/DC2C_conf.json"),
                                        QString("etc/psa_config/DC2C_cash.json"),
                                        QString("etc/psa_config/DC2C_device.json"),
                                        QString("etc/psa_config/DC2C_print01.json"),
                                        QString("etc/psa_config/DC2C_print02.json"),
                                        QString("etc/psa_config/DC2C_print03.json"),
                                        QString("etc/psa_config/DC2C_print04.json"),
                                        QString("etc/psa_config/DC2C_print05.json"),
                                        QString("etc/psa_config/DC2C_print06.json"),
                                        QString("etc/psa_config/DC2C_print07.json"),
                                        QString("etc/psa_config/DC2C_print08.json"),
                                        QString("etc/psa_config/DC2C_print09.json"),
                                        QString("etc/psa_config/DC2C_print10.json"),
                                        QString("etc/psa_config/DC2C_print11.json"),
                                        QString("etc/psa_config/DC2C_print12.json"),
                                        QString("etc/psa_config/DC2C_print13.json"),
                                        QString("etc/psa_config/DC2C_print14.json"),
                                        QString("etc/psa_config/DC2C_print15.json"),
                                        QString("etc/psa_config/DC2C_print16.json"),
                                        QString("etc/psa_config/DC2C_print17.json"),
                                        QString("etc/psa_config/DC2C_print18.json"),
                                        QString("etc/psa_config/DC2C_print19.json"),
                                        QString("etc/psa_config/DC2C_print20.json"),
                                        QString("etc/psa_config/DC2C_print21.json"),
                                        QString("etc/psa_config/DC2C_print22.json"),
                                        QString("etc/psa_config/DC2C_print23.json"),
                                        QString("etc/psa_config/DC2C_print24.json"),
                                        QString("etc/psa_config/DC2C_print25.json"),
                                        QString("etc/psa_config/DC2C_print26.json"),
                                        QString("etc/psa_config/DC2C_print27.json"),
                                        QString("etc/psa_config/DC2C_print28.json"),
                                        QString("etc/psa_config/DC2C_print29.json"),
                                        QString("etc/psa_config/DC2C_print30.json"),
                                        QString("etc/psa_config/DC2C_print31.json"),
                                        QString("etc/psa_config/DC2C_print32.json")})));
/*
    bool checkDownloadedJsonVersions(QStringList const& jsonFileNames);

    hwinf *hw() { return m_hw; }
    hwinf const *hw() const { return m_hw; }

    //QString customerId() { return m_customerId; }
    //QString const customerId() const { return m_customerId; }

    QString branchName() { return m_branchName; }
    QString const branchName() const { return m_branchName; }

    //QString repositoryPath() { return m_repositoryPath; }
    //QString const repositoryPath() const { return m_repositoryPath; }

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