#include <sys/cdefs.h>
#include <stdio.h>
#include <inttypes.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp_log.h>
#include <nvs_flash.h>
#include <mqtt_client.h>
#include <esp_crt_bundle.h>
#include <led_strip.h>
#include <esp_timer.h>
#include <driver/gpio.h>

#include "LED_Segments.h"

// Constants
#define LED_STRIP_RMT_RES_HZ  (10 * 1000 * 1000)
#define TOPIC_BUFFER_SIZE 50

// Global variables
LED_Segments segments[CONFIG_LED_SEGMENT_COUNT];

esp_mqtt_client_handle_t mqtt_client;
led_strip_handle_t led_internal;
led_strip_handle_t led_segments[6];

led_strip_config_t segments_led_configs[6];
led_strip_rmt_config_t rmt_config;

void init_led_strip() 
{
    led_strip_config_t strip_config = 
    {
        .strip_gpio_num = 0,
        .max_leds = CONFIG_LED_SEGMENT_COUNT * CONFIG_LED_SEGMENT_SIZE,
        .led_pixel_format = LED_PIXEL_FORMAT_GRB,
        .led_model = LED_MODEL_WS2812,
        .flags.invert_out = false,
    };

    strip_config.strip_gpio_num = CONFIG_PIN_SEGMENT_DATA_0;
    segments_led_configs[0] = strip_config;

    strip_config.strip_gpio_num = CONFIG_PIN_SEGMENT_DATA_1;
    segments_led_configs[1] = strip_config;

    strip_config.strip_gpio_num = CONFIG_PIN_SEGMENT_DATA_2;
    segments_led_configs[2] = strip_config;

    strip_config.strip_gpio_num = CONFIG_PIN_SEGMENT_DATA_3;
    segments_led_configs[3] = strip_config;

    strip_config.strip_gpio_num = CONFIG_PIN_SEGMENT_DATA_4;
    segments_led_configs[4] = strip_config;

    strip_config.strip_gpio_num = CONFIG_PIN_SEGMENT_DATA_5;
    segments_led_configs[5] = strip_config;

    led_strip_rmt_config_t rmt = 
    {
        .clk_src = RMT_CLK_SRC_DEFAULT,
        .resolution_hz = LED_STRIP_RMT_RES_HZ,
        .flags.with_dma = true,
    };
    rmt_config = rmt;


    strip_config.strip_gpio_num = CONFIG_PIN_INTERNAL_LED;
    led_strip_new_rmt_device(&strip_config, &rmt_config, &led_internal);
}

// LED Task
void vTaskLEDUpdate( void * pvParameters )
{
    while(1)
    {
        ESP_ERROR_CHECK(led_strip_new_rmt_device(&segments_led_configs[0], &rmt_config, &led_segments[0]));
        ESP_ERROR_CHECK(led_strip_new_rmt_device(&segments_led_configs[1], &rmt_config, &led_segments[1]));
        ESP_ERROR_CHECK(led_strip_new_rmt_device(&segments_led_configs[2], &rmt_config, &led_segments[2]));

        ESP_ERROR_CHECK(led_strip_set_pixel(led_segments[0], 0 , 0xFF, 0xFF, 0xFF));
        ESP_ERROR_CHECK(led_strip_set_pixel(led_segments[1], 0 , 0xFF, 0xFF, 0xFF));
        ESP_ERROR_CHECK(led_strip_set_pixel(led_segments[2], 0 , 0xFF, 0xFF, 0xFF));

        ESP_ERROR_CHECK(led_strip_del(led_segments[0]));
        ESP_ERROR_CHECK(led_strip_del(led_segments[1]));
        ESP_ERROR_CHECK(led_strip_del(led_segments[2]));

        ESP_ERROR_CHECK(led_strip_new_rmt_device(&segments_led_configs[3], &rmt_config, &led_segments[3]));
        ESP_ERROR_CHECK(led_strip_new_rmt_device(&segments_led_configs[4], &rmt_config, &led_segments[4]));
        ESP_ERROR_CHECK(led_strip_new_rmt_device(&segments_led_configs[5], &rmt_config, &led_segments[5]));

        ESP_ERROR_CHECK(led_strip_set_pixel(led_segments[3], 0 , 0xFF, 0xFF, 0xFF));
        ESP_ERROR_CHECK(led_strip_set_pixel(led_segments[4], 0 , 0xFF, 0xFF, 0xFF));
        ESP_ERROR_CHECK(led_strip_set_pixel(led_segments[5], 0 , 0xFF, 0xFF, 0xFF));

        ESP_ERROR_CHECK(led_strip_del(led_segments[3]));
        ESP_ERROR_CHECK(led_strip_del(led_segments[4]));
        ESP_ERROR_CHECK(led_strip_del(led_segments[5]));

        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void app_main(void)
{
    init_led_strip();

    TaskHandle_t xHandle_LEDUpdate = NULL;
    xTaskCreate( vTaskLEDUpdate, "LED", 200, NULL, tskIDLE_PRIORITY, &xHandle_LEDUpdate );
}