#ifndef MESSAGE_HELPER_H_INCLUDED
#define MESSAGE_HELPER_H_INCLUDED

#include <cinttypes>
#include <QByteArray>
#include <QByteArrayList>
#include <QString>
#include <QDateTime>

class MessageHelper {
public:
    enum PacketType : std::uint8_t {
        POS_ECR = 0,
        // POS_EXT = 1,
        MESSAGE_RECEIVED_POSITIVE_ACK = 0x0A,
        MESSAGE_RECEIVED_NEGATIVE_ACK = 0x0F
        // POS_HOST_FORMAT_1_ENCRYPTED   = 0x11,
        // POS_HOST_FORMAT_1_UNENCRYPTED = 0x21
    };

    enum AsyncPosCommand : std::uint8_t {
        LOGIN  = 0,
        LOGOUT = 1,
        AUTHORIZE = 2,
        CLOSE_DOCUMENT = 3
    };

    explicit MessageHelper(QString const &posID = "T-TPS-SELF2002in",
                           QString const &apak = "8AC304380E0E476BA2558B75DB9E2516");
    explicit MessageHelper(QByteArray const &posID, QString const &apak);
    ~MessageHelper();


    void createRawPacket(PacketType PacketType,
                         QByteArray const &encryptedPacketId,
                         QByteArray const &message);

    bool insertEncryptedPacketID(QByteArray const &encryptedPacketID);

    QByteArrayList createLoginMessageChunksToSend(char etx);
    QByteArrayList createLogoutMessageChunksToSend(char etx);
    QByteArrayList createAuthorizeMessageChunksToSend(char etx);
    QByteArrayList createCloseDocumentMessageChunksToSend(char etx);
    QByteArrayList const &createMessageChunksToSend(AsyncPosCommand cmd, char etx);

// private:

    QByteArray m_posID;
    QByteArray m_apak;
    uint8_t m_posIDLength;
    QByteArray m_messageHeaderPrefix;
    QByteArray m_rawPacket; // without leading STX and trailing [ETX(1/2), LRC]
    QByteArray m_loginMessage;
    QByteArray m_logoutMessage;
    QByteArray m_authorizeMessage;
    QByteArray m_cancelAuthorizeMessage;
    QByteArray m_pingMessage;
    QByteArray m_printResultMessage;
    QByteArray m_closeDocumentMessage;
    QByteArray m_uniqueTransactionID;
    QString m_price;
    QByteArrayList m_messageChunkList;

    bool setMessageHeaderPacketType(PacketType packetType);

    bool createMessageHeaderPrefix(PacketType packetType, QByteArray const &encryptedPacketID);
    void createLoginMessage();
    void createLogoutMessage();
    void createAuthorizeMessage();
    void createCancelAuthorizeMessage();
    void createPingMessage();
    void createCloseDocumentMessage(bool storno = false);
    void createPrintResultMessage();

    void handleCommand(AsyncPosCommand command, char status);
    //r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt

    void handleMessage(char const *pData);

    QByteArray const &generateUniqueTransactionID(QString const &machineNr, QString const &customerNumer);

    static QByteArray const &mask(QByteArray &messageChunk);
    static QByteArray const &unMask(QByteArray &messageChunk);
    static uint32_t secsSinceJan2017(QDateTime const &dt = QDateTime::currentDateTime());

    struct AsynchBillData {
        char time[20];
        char id[37];
        char printId[129];
        char docNr[33];
        //unsigned char amount[10];
        //unsigned char token[25];
        //unsigned char result[8];
        //unsigned char authCode[7];
        //unsigned char rrn[13];
        //unsigned char stan[7];
        //unsigned char cardtype[33];
        char errCode[17];
        //unsigned char receiptData[IUC_ASYNCHPOS_RECEIPT_LENGTH];
    };

    struct AuthorizationResult {
        QString m_id;       // max. 36
        QString m_docNr;    // max. 32
        QString m_result;   // "OK" or "ERROR"
    };

    static AsynchBillData m_asyncBillData;
    static AuthorizationResult m_authorizationResult;
};

#endif // MESSAGE_HELPER_H_INCLUDED