#pragma once
#include <stdint.h>
#include "gobotrpc.hpp"
#include "uart_ctrl_hardware.hpp"

struct HubInfo {
    uint8_t slotNumbers;
};

typedef void (*UART_CTRL_Callback_Packet)(void * args, RPCPackage package);
typedef void (*UART_CTRL_Callback_PerformScan)(void * args, bool enable);
typedef void (*UART_CTRL_Callback_ReqSlotUpdate)(void * args, bool enable);
typedef HubInfo (*UART_CTRL_Callback_GetInfo)(void * args);

void externalCallback_RX(void * args, char * data, size_t length);

class UART_CTRL_Interface {
private:
    UART_CTRL_Callback_Packet packetCallback;
    UART_CTRL_Callback_PerformScan performScanCallback;
    UART_CTRL_Callback_ReqSlotUpdate reqSlotUpdateCallback;
    UART_CTRL_Callback_GetInfo getInfoCallback;
    void * packetCallbackArgs;
    void * performScanCallbackArgs;
    void * reqSlotUpdateCallbackArgs;
    void * getInfoCallbackArgs;

    I_UART_CTRL_Hardware_Handler * handler;
protected:
    void onRX_Packet(char * data, size_t length);
    void onRX_PerformScan(char * data, size_t length);
    void onRX_ReqSlotUpdate(char * data, size_t length);
    void onRX_GetInfo(char * data, size_t length);

public:
    UART_CTRL_Interface(I_UART_CTRL_Hardware_Handler * handler);
    void onRX(char * data, size_t length);

    void pushPacket(RPCPackage package);
    void pushScanResulst(uint32_t addr, bool running);
    void pushPackageSlotUpdate(bool complete, bool inUse, uint32_t slot, uint32_t addr, uint32_t timestamp, uint32_t bits);
    void pushInfo(uint8_t slotNumbers);

    void registerCallback_Packet(UART_CTRL_Callback_Packet callback, void * args);
    void registerCallback_PerformScan(UART_CTRL_Callback_PerformScan callback, void * args);
    void registerCallback_ReqSlotUpdate(UART_CTRL_Callback_ReqSlotUpdate callback, void * args);
    void registerCallback_GetInfo(UART_CTRL_Callback_GetInfo callback, void * args);
};


enum UART_CTRL_Command_ID {
    UART_CMD_PACKET = 0x01, // Host <-> Hub
    UART_CMD_PERFORM_SCAN = 0x02, // Host -> Hub
    UART_CMD_SCAN_RESULT = 0x03, // Hub -> Host
    UART_CMD_SLOT_UPDATE = 0x04, // Hub -> Host
    UART_CMD_REQ_SLOT_UPDATE = 0x05, // Host -> Hub
    UART_CMD_INFO = 0xff, // Host -> Hub, Hub -> Host
};