#ifndef STM32BURNPROTOCOL_H
#define STM32BURNPROTOCOL_H

#include "protocol/BurnProtocol.h"
#include <QObject>

struct STM32BurnDevInfo;

class STM32BurnProtocol : public QObject, public BurnProtocol {
    Q_OBJECT
public:
    QString protoclolId() const override {return QStringLiteral("stm32");}

    int maxReadBlockSize() const override;
    int maxWriteBlockSize() const override;

    void setPort(BurnPort &port, LQError &err) override;

    void autobaud(int tout, LQError &err) override;
    void getDevInfo(BurnDeviceInfo &info, LQError &err) override;
    void devCleanup(LQError &err) override;
    void writeMemBlock(burn_mem_addr_t addr, const QByteArray &data, LQError &err) override;
    void readMemBlock(burn_mem_addr_t addr, int size, QByteArray &data, LQError &err) override;
    void startApp(burn_mem_addr_t addr, LQError &err) override;
private:
    static const int default_cmd_tout = 1000;
    static const int reset_wait_time  = 100;
    static const int reset_autobaud_tout  = 200;

    void checkPortInit(LQError &err);
    void checkDevInfoValid(LQError &err);
    void updateDevInfo(LQError &err);


    void sendComplemented(quint8 data, LQError &err);
    void sendCmd(quint8 cmd, LQError &err);
    void recvCmdAck(quint8 cmd, LQError &err, int tout = default_cmd_tout);
    void recvDataAck(LQError &err, int tout = default_cmd_tout);

    QByteArray recvCmdData(int size, LQError &err, int tout = default_cmd_tout);
    QByteArray recvCmdVarData(LQError &err, int tout = default_cmd_tout);
    void execCmd(quint8 cmd, LQError &err, int tout = default_cmd_tout);

    void resetAutobaud(LQError &err);
    void readOptions(QByteArray &options, LQError &err);

    bool checkCmdSupport(quint16 cmd) const;
    bool cmdRdpModeAvailable(quint8 cmd) const; /* доступна ли команда в RDP-режиме */

    void cmdExecGet(quint8 &boot_ver, QList<quint8> &cmd_list, LQError &err);
    void cmdExecGetID(quint16 &id, LQError &err);
    void cmdExecMemRd(quint32 addr, int size, QByteArray &data, LQError &err);
    void cmdExecMemWr(quint32 addr, const QByteArray &data, LQError &err);
    void cmdExecGo(quint32 addr, LQError &err);
    void cmdExecMassErase(LQError &err);
    void cmdExecRdProtect(LQError &err);
    void cmdExecRdUnprotect(LQError &err);
    void cmdExecWrUnprotect(LQError &err);


    uint8_t calcCheckSum(const QByteArray &data, int size) const;
    int massEraseCmdTimeout() const;

    BurnPort *m_port {nullptr};
    const STM32BurnDevInfo *m_devInfo {nullptr};

    quint8 m_boot_ver {0};    
    QList<quint8> m_supported_cmd_list;
};

#endif // STM32BURNPROTOCOL_H
