#ifndef LED_DISPLAY
#define LED_DISPLAY

#include <Arduino.h>
#include <ArduinoJson.h>
#include "mbedtls/md.h"
#include "EepromManager.h"
#include "BluetoothLeUartServer.h"
#include "LedDisplayController.h"


class LedDisplay : protected BluetoothLeUartServerCallbacks
{

public:
    template<typename T_COLOR_FEATURE, typename T_METHOD>
    explicit LedDisplay(String deviceName, NeoPixelBrightnessBusGfx<T_COLOR_FEATURE, T_METHOD> *ledDisplayMatrix)
    {
        this->lastKeepAlive = -1;
        this->sessionAuthorized = false;

        // init eeprom manager
        this->eepromManager = new EepromManager();

        // init led display controller
        this->ledDisplayController = new LedDisplayController(ledDisplayMatrix);
        this->ledDisplayController->registerEepromUnit(this->eepromManager);

        // register eeprom for this class
        this->eepromUnit = this->eepromManager->registerEempromUnit(sizeof(DisplayProperties));
        this->loadProperties();

        // init ble server
        this->bleServer = new BluetoothLeUartServer(this->properties.deviceName, "92fecb20-1406-426a-afa5-cd5c1f306462", "92fecb21-1406-426a-afa5-cd5c1f306462", "92fecb22-1406-426a-afa5-cd5c1f306462");
        this->bleServer->setCallbacks(this);

    };


    // befriend for callbacks
    friend class BluetoothLeUartServer;

    void loop();

protected:
    // calbacks for BluetoothLeUartServerCallbacks
    void onDeviceConnectedChanged(bool deviceConnected) override;
    void onDataReceived(String data) override;

private:

    enum DisplayCommand
    {
        AuthenticateCommand = 0,
        KeepAliveCommand = 1,
        GetAllTextSetsCommand = 10,
        GetTextSetParameterCommand = 11,
        GetDisplayBrightnessCommand = 12,
        SetTextSetParameterCommand = 20,
        SetDisplayBrightnessCommand = 21,
        SetDisplayCodeCommand = 22,
        SetDisplayNameCommand = 23
    };

    enum DisplayStatusCode
    {
        Success = 200,
        BadRequestError = 400,
        Unauthorized = 401,
        InternalError = 500,
        DisplayControllerError = 501
    };

    unsigned long lastKeepAlive;
    const int maximumKeepAliveDelay = 10000;
    bool sessionAuthorized;

    typedef struct {
        char deviceName[50];
        char deviceCode[5];
        char valid[3];
    } DisplayProperties;

    DisplayProperties properties;

    EepromManager* eepromManager;
    EepromUnit* eepromUnit;
    LedDisplayController* ledDisplayController;
    BluetoothLeUartServer* bleServer;

    bool loadProperties();
    bool storeProperties();

    String sha256(String payload);
};

#endif // LED_DISPLAY