#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/rmt.h"
#include "esp_log.h"

#define RMT_TX_CHANNEL RMT_CHANNEL_0
#define RMT_TX_GPIO    8
#define LED_STRIP_LEN  30

static const char *TAG = "ws2812";

typedef struct {
    uint8_t r, g, b;
} rgb_t;

static rgb_t led_strip[LED_STRIP_LEN];

static void led_strip_fill_rgb(uint8_t r, uint8_t g, uint8_t b) {
    for (int i = 0; i < LED_STRIP_LEN; i++) {
        led_strip[i].r = r;
        led_strip[i].g = g;
        led_strip[i].b = b;
    }
}

static void rmt_tx_init() {
    rmt_config_t config = RMT_DEFAULT_CONFIG_TX(RMT_TX_GPIO, RMT_TX_CHANNEL);
    config.clk_div = 2;
    ESP_ERROR_CHECK(rmt_config(&config));
    ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
}

static void led_strip_update() {
    rmt_item32_t items[LED_STRIP_LEN * 24];
    int item_idx = 0;

    for (int i = 0; i < LED_STRIP_LEN; i++) {
        uint32_t color = (led_strip[i].g << 16) | (led_strip[i].r << 8) | led_strip[i].b;
        for (int bit = 23; bit >= 0; bit--) {
            if (color & (1 << bit)) {
                items[item_idx].level0 = 1;
                items[item_idx].duration0 = 32;  // 800ns
                items[item_idx].level1 = 0;
                items[item_idx].duration1 = 16;  // 400ns
            } else {
                items[item_idx].level0 = 1;
                items[item_idx].duration0 = 16;  // 400ns
                items[item_idx].level1 = 0;
                items[item_idx].duration1 = 32;  // 800ns
            }
            item_idx++;
        }
    }

    ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, items, item_idx, true));
    ESP_ERROR_CHECK(rmt_wait_tx_done(RMT_TX_CHANNEL, portMAX_DELAY));
}

void app_main() {
    rmt_tx_init();
    uint8_t r = 255, g = 0, b = 0;

    while (1) {
        // Cycle through RGB colors
        if (r == 255 && g < 255 && b == 0) {
            g++;
        } else if (g == 255 && r > 0 && b == 0) {
            r--;
        } else if (g == 255 && b < 255 && r == 0) {
            b++;
        } else if (b == 255 && g > 0 && r == 0) {
            g--;
        } else if (b == 255 && r < 255 && g == 0) {
            r++;
        } else if (r == 255 && b > 0 && g == 0) {
            b--;
        }

        led_strip_fill_rgb(r, g, b);
        led_strip_update();
        vTaskDelay(pdMS_TO_TICKS(10)); // Adjust delay to control speed of color cycling
    }
}