#include "uart_ctrl.hpp"
#include "gobotrpc.hpp"
#include <string.h>

void externalCallback_RX(void * args, char * data, size_t length) {
    UART_CTRL_Interface *interface = (UART_CTRL_Interface *)args;
    interface->onRX(data, length);
}

void UART_CTRL_Interface::onRX(char * data, size_t length) {
    uint8_t cmd = data[0];
    switch (cmd) {
    case UART_CMD_PACKET:
        onRX_Packet(data, length);
        break;
    
    case UART_CMD_PERFORM_SCAN:
        onRX_PerformScan(data, length);
        break;

    case UART_CMD_REQ_SLOT_UPDATE:
        onRX_ReqSlotUpdate(data, length);
        break;

    case UART_CMD_INFO:
        onRX_GetInfo(data, length);
        break;

    default:
        break;
    }
}

void UART_CTRL_Interface::onRX_Packet(char *data, size_t length) {
    if(length < 7)
        return;


    if (packetCallback != nullptr) {
        RPCPackage package;
        package.length = data[1];
        package.type = RPCType(data[2] & 0b11);
        package.rpcNum = RPCNumber(data[2] >> 4);
        memcpy(&package.addr, &data[3], 4);
        memcpy(package.buffer, &data[7], package.length);
 
        packetCallback(packetCallbackArgs, package);
    }
}

void UART_CTRL_Interface::onRX_PerformScan(char *data, size_t length) {
    if(length < 2)
        return;
    
    if (performScanCallback != nullptr)
        performScanCallback(performScanCallbackArgs, data[1] == 1);
}

void UART_CTRL_Interface::onRX_ReqSlotUpdate(char *data, size_t length) {
    if (length < 2)
        return;

    if (reqSlotUpdateCallback != nullptr)
        reqSlotUpdateCallback(reqSlotUpdateCallbackArgs, data[1] == 1);
}

void UART_CTRL_Interface::onRX_GetInfo(char *data, size_t length) {
    if (length < 1)
        return;

    if (getInfoCallback != nullptr)
        getInfoCallback(getInfoCallbackArgs);
}