#include "UsbDataHandler.h"
#include "light.pb.h"
#include "FreeRTOS.h"
#include "cmsis_os2.h"
#include "CLS.h"
#include "CLS_BSP.h"
#include "CLSAddress.h"
#include "BSP_EE24.h"
#include "LightTask.h"

// Memory for the task
StaticTask_t LightTask_cb;
uint32_t LightTask_stk[128];
// Attributes for the task
osThreadId_t LightTask_id;
const osThreadAttr_t LightTask_attr = {
  .name = "LightTask",
  .attr_bits = 0U,
  .cb_mem = &LightTask_cb,
  .cb_size = sizeof(LightTask_cb),
  .stack_mem = LightTask_stk,
  .stack_size = sizeof(LightTask_stk),
  .priority = osPriorityNormal,
};

static cls_light_GlobalBrightness msg_cls_light_GlobalBrightness;
static cls_light_GlobalTheme msg_cls_light_GlobalTheme;
static cls_light_ThemeSettings msg_cls_light_ThemeSettings;
static cls_light_SaveThemeSettings msg_cls_light_SaveThemeSettings;

static volatile struct LightSettings_s {
    volatile uint8_t brightness;
    volatile uint8_t theme;
} lightSettings;

// these are used to save these settings some tome after they change
static const uint32_t settingSaveTimeout = 10*1000;
static volatile uint32_t settingChangeTime = 0;

void LightTask_func(void *argument);

void LightTask_start() {
  // Task functionality here
   LightTask_id = osThreadNew(LightTask_func, NULL, &LightTask_attr);
}



void LightTask_func(void *argument) { 
    osDelay(10);

    BSP_EE24_PartRead(BSP_EE24_PART_GLOBAL_LIGHT, (uint8_t*) &lightSettings, sizeof(lightSettings));
    uint16_t msg_global_light = GENERATE_CLS_ADDRESS(CLS_CODE_MESSAGE, GLOBAL_CAST_CLS_ADDRESS, CLS_CH_MSG_LIGHT);
    CLS_BSP_TxHeaderType can_header = CREATE_BSP_CAN_HEADER(msg_global_light, CLS_BSP_DLC_BYTES_2);

    uint32_t tick = osKernelGetTickCount();
    while (1)
    {
        tick += 50;
        osDelayUntil(tick);
        CLS_BSP_CAN_AddMessageToSend(&can_header,(uint8_t*)&lightSettings);

        if( settingChangeTime !=0 && tick > settingChangeTime + settingSaveTimeout) {
            BSP_EE24_PartWrite(BSP_EE24_PART_GLOBAL_LIGHT, (uint8_t*) &lightSettings, sizeof(lightSettings));
            settingChangeTime = 0;
        }
    }
}

void DataClbk_cls_light_GlobalBrightness(void* msg, uint32_t length) {
    DATA_CLBK_SETUP(cls_light_GlobalBrightness);
    lightSettings.brightness = msg_cls_light_GlobalBrightness.brightness;
    settingChangeTime = osKernelGetTickCount();
}

void DataClbk_cls_light_GlobalTheme(void* msg, uint32_t length) {
    DATA_CLBK_SETUP(cls_light_GlobalTheme);
    lightSettings.theme = msg_cls_light_GlobalTheme.theme;
    settingChangeTime = osKernelGetTickCount();
}

void DataClbk_cls_light_ThemeSettings(void* msg, uint32_t length) {
    DATA_CLBK_SETUP(cls_light_ThemeSettings);
    uint8_t device = msg_cls_light_ThemeSettings.deviceId;
    uint8_t theme = msg_cls_light_ThemeSettings.theme & 0x3;

    uint16_t msg_light_setting = GENERATE_CLS_ADDRESS(CLS_CODE_CONFIG, device, theme);
    CLS_BSP_TxHeaderType can_header = CREATE_BSP_CAN_HEADER(msg_light_setting, CLS_BSP_DLC_BYTES_8);

    RGB_Theme_t data = {0};
    data.animation = msg_cls_light_ThemeSettings.animation;
    data.max_brighness = msg_cls_light_ThemeSettings.brightness;
    data.color.r = (msg_cls_light_ThemeSettings.rgb) & 0xFF;
    data.color.g = (msg_cls_light_ThemeSettings.rgb>>8) & 0xFF;
    data.color.b = (msg_cls_light_ThemeSettings.rgb>>16) & 0xFF;
    
    CLS_BSP_CAN_AddMessageToSend(&can_header, (uint8_t*)&data);
}   



void DataClbk_cls_light_SaveThemeSettings(void* msg, uint32_t length)  {
    DATA_CLBK_SETUP(cls_light_SaveThemeSettings);
    uint8_t device = msg_cls_light_SaveThemeSettings.deviceId;
    uint16_t msg_light_setting = GENERATE_CLS_ADDRESS(CLS_CODE_CONFIG, device, 4);
    CLS_BSP_TxHeaderType can_header = CREATE_BSP_CAN_HEADER(msg_light_setting, CLS_BSP_DLC_BYTES_1);
    CLS_BSP_CAN_AddMessageToSend(&can_header, (uint8_t*)"X");
}