#include "leds.h"
#include "led_strip.h"
#include <esp_log.h>
#include "state_tracking.h"
#include <cstring>

static const char* TAG = "leds";

static led_strip_handle_t leds;

// TODO: rename these to playback_handler
static bool replay_handler(const char* event, char* arg) {
    if (strcmp(event, "LED_SET") == 0) {
        uint32_t led = atoi(strtok(arg, ","));
        uint32_t color = atoi(strtok(NULL, ","));
        led_set(led, color);
        return true;
    }
    if (strcmp(event, "LED_FLUSH") == 0) {
        leds_flush();
        return true;
    }
    if (strcmp(event, "LED_CLR") == 0) {
        leds_clear();
        return true;
    }

    return false;
}

void init_leds() {
    ESP_LOGI(TAG, "Initializing LEDs...");

    led_strip_config_t strip_config = {
        .strip_gpio_num = NEOPIXEL_PIN,
        .max_leds = LED_COUNT,
        .led_pixel_format = LED_PIXEL_FORMAT_GRB,
        .led_model = LED_MODEL_WS2812
    };

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

    ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &leds));

    register_replay_fn(replay_handler);

    ESP_LOGI(TAG, "LEDs initialized!");
}

void led_set(uint32_t led, uint8_t r, uint8_t g, uint8_t b) {
    led_strip_set_pixel(leds, led, r, g, b);

    if (is_state_tracking()) {
        char buf[32];
        uint32_t color = (r << 16) | (g << 8) | b;
        sprintf(buf, "%ld,%ld", led, color);
        event_occured("LED_SET", buf);
    }
}

void led_set(uint32_t led, uint32_t color) {
    led_set(led, (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF);
}

void leds_flush() {
    led_strip_refresh(leds);

    if (is_state_tracking()) {
        event_occured("LED_FLUSH", NULL);
    }
}

void leds_clear() {
    led_strip_clear(leds);

    if (is_state_tracking()) {
        event_occured("LED_CLR", NULL);
    }
}
