/*
 * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_idf_version.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "led_indicator.h"

#include "base.h"


#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)

static const char* TAG = "task_ws2812_init";
static led_indicator_handle_t led_handle = NULL;

/**
 * @brief Define blinking type and priority.
 *
 */
enum {
	BLINK_DOUBLE_RED = 0,
	BLINK_TRIPLE_GREEN,
	BLINK_WHITE_BREATHE_SLOW,
	BLINK_WHITE_BREATHE_FAST,
	BLINK_BLUE_BREATH,
	BLINK_COLOR_HSV_RING,
	BLINK_COLOR_RGB_RING,
#if WS2812_STRIPS_NUM > 1
	BLINK_FLOWING,
#endif
	BLINK_MAX,
};

/**
 * @brief Blinking twice times in red has a priority level of 0 (highest).
 *          红色闪 2 次
 * action type in this step
 * hold on or off, set 0 if LED_BLINK_STOP() or LED_BLINK_LOOP
 * hold time(ms), set 0 if not LED_BLINK_HOLD
 *
 */
static const blink_step_t double_red_blink[] = {
	/*!< Set color to red by R:255 G:0 B:0 */
	{LED_BLINK_RGB, SET_RGB(255, 0, 0), 0},     // 设置为红色
	{LED_BLINK_HOLD, LED_STATE_ON, 500},        // 保持500ms亮
	{LED_BLINK_HOLD, LED_STATE_OFF, 500},       // 保持500ms灭
	{LED_BLINK_HOLD, LED_STATE_ON, 500},        // 保持500ms亮
	{LED_BLINK_HOLD, LED_STATE_OFF, 500},       // 保持500ms灭
	{LED_BLINK_STOP, 0, 0},                     // 停止
};

/**
 * @brief Blinking three times in green with a priority level of 1.
 *          绿色闪 3 次
 */
static const blink_step_t triple_green_blink[] = {
	/*!< Set color to green by R:0 G:255 B:0 */
	{LED_BLINK_RGB, SET_RGB(0, 255, 0), 0},     // 设置为绿色
	{LED_BLINK_HOLD, LED_STATE_ON, 500},        // 保持500ms亮
	{LED_BLINK_HOLD, LED_STATE_OFF, 500},       // 保持500ms灭
	{LED_BLINK_HOLD, LED_STATE_ON, 500},        // 保持500ms亮
	{LED_BLINK_HOLD, LED_STATE_OFF, 500},       // 保持500ms灭
	{LED_BLINK_HOLD, LED_STATE_ON, 500},        // 保持500ms亮
	{LED_BLINK_HOLD, LED_STATE_OFF, 500},       // 保持500ms灭
	{LED_BLINK_STOP, 0, 0},
};

/**
 * @brief Slow breathing in white with a priority level of 2.
 *          白色呼吸慢
 */
static const blink_step_t breath_white_slow_blink[] = {
	/*!< Set Color to white and brightness to zero by H:0 S:0 V:0 */
	{LED_BLINK_HSV, SET_HSV(0, 0, 0), 0},       // 设置为白色
	{LED_BLINK_BREATHE, LED_STATE_ON, 1000},    // 呼吸1000ms亮
	{LED_BLINK_BREATHE, LED_STATE_OFF, 1000},    // 呼吸1000ms灭
	{LED_BLINK_LOOP, 0, 0},                     // 循环
};

/**
 * @brief Fast breathing in white with a priority level of 3.
 *          白色呼吸快
 */
static const blink_step_t breath_white_fast_blink[] = {
	/*!< Set Color to white and brightness to zero by H:0 S:0 V:0 */
	{LED_BLINK_HSV, SET_HSV(0, 0, 0), 0},       // 设置为白色
	{LED_BLINK_BREATHE, LED_STATE_ON, 500},    // 呼吸500ms亮
	{LED_BLINK_BREATHE, LED_STATE_OFF, 500},    // 呼吸500ms灭
	{LED_BLINK_LOOP, 0, 0},                     // 循环
};

/**
 * @brief Breathing in green with a priority level of 4.
 *          蓝色呼吸
 */
static const blink_step_t breath_blue_blink[] = {
	/*!< Set Color to blue and brightness to zero by H:240 S:255 V:0 */
	{LED_BLINK_HSV, SET_HSV(240, MAX_SATURATION, 0), 0},    // 设置为蓝色
	{LED_BLINK_BREATHE, LED_STATE_ON, 1000},    // 呼吸1000ms亮
	{LED_BLINK_BREATHE, LED_STATE_OFF, 1000},    // 呼吸1000ms灭
	{LED_BLINK_LOOP, 0, 0},                     // 循环
};

/**
 * @brief Color gradient by HSV with a priority level of 5.
 *          HSV 渐变
 */
static const blink_step_t color_hsv_ring_blink[] = {
	/*!< Set Color to RED */
	{LED_BLINK_HSV, SET_HSV(0, MAX_SATURATION, MAX_BRIGHTNESS), 0},
	{LED_BLINK_HSV_RING, SET_HSV(240, MAX_SATURATION, 127), 2000},
	{LED_BLINK_HSV_RING, SET_HSV(0, MAX_SATURATION, MAX_BRIGHTNESS), 2000},
	{LED_BLINK_LOOP, 0, 0},
};

/**
 * @brief Color gradient by RGB with a priority level of 5.
 *
 */
static const blink_step_t color_rgb_ring_blink[] = {
	/*!< Set Color to Green */
	{LED_BLINK_RGB, SET_RGB(0, 255, 0), 0},     // 设置为绿色
	{LED_BLINK_RGB_RING, SET_RGB(255, 0, 255), 2000}, // 渐变为紫色
	{LED_BLINK_RGB_RING, SET_RGB(0, 255, 0), 2000},   // 渐变为绿色
	{LED_BLINK_LOOP, 0, 0},                         // 循环
};


#if WS2812_STRIPS_NUM > 1
/**
 * @brief Flowing lights with a priority level of 6(lowest).
 *        Insert the index:MAX_INDEX to control all the strips
 *
 */
static const blink_step_t flowing_blink[] = {
	{LED_BLINK_HSV, SET_IHSV(MAX_INDEX, 0, MAX_SATURATION, MAX_BRIGHTNESS), 0},
	{LED_BLINK_HSV_RING, SET_IHSV(MAX_INDEX, MAX_HUE, MAX_SATURATION, MAX_BRIGHTNESS), 2000},
	{LED_BLINK_LOOP, 0, 0},
};
#endif

blink_step_t const* led_mode[] = {
	[BLINK_DOUBLE_RED] = double_red_blink,
	[BLINK_TRIPLE_GREEN] = triple_green_blink,
	[BLINK_WHITE_BREATHE_SLOW] = breath_white_slow_blink,
	[BLINK_WHITE_BREATHE_FAST] = breath_white_fast_blink,
	[BLINK_BLUE_BREATH] = breath_blue_blink,
	[BLINK_COLOR_HSV_RING] = color_hsv_ring_blink,
	[BLINK_COLOR_RGB_RING] = color_rgb_ring_blink,
#if WS2812_STRIPS_NUM > 1
	[BLINK_FLOWING] = flowing_blink,
#endif
	[BLINK_MAX] = NULL,
};

static blink_step_t my_blink_step[] = {
	/*!< Set color to green by R:0 G:255 B:0 */
	{LED_BLINK_RGB, SET_RGB(255, 255, 255), 0},     // 设置为绿色
	{LED_BLINK_HOLD, LED_STATE_ON, 500},        // 保持500ms亮
	{LED_BLINK_HOLD, LED_STATE_OFF, 500},       // 保持500ms灭
	{LED_BLINK_LOOP, 0, 0},
};

blink_step_t const* my_led_mode[] = {
	[0] = my_blink_step,
	[BLINK_MAX] = NULL,
};

void ws2812_init(void)
{

	led_strip_config_t strip_config = {
		.strip_gpio_num = WS2812_GPIO_NUM,        // The GPIO that connected to the LED strip's data line
		.max_leds = WS2812_STRIPS_NUM,            // The number of LEDs in the strip,
		.led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip
		.led_model = LED_MODEL_WS2812,            // LED strip model
		.flags.invert_out = false,                // whether to invert the output signal
	};

	// LED strip backend configuration: RMT
	led_strip_rmt_config_t rmt_config = {
		.clk_src = RMT_CLK_SRC_DEFAULT,        // different clock source can lead to different power consumption
		.resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency
		.flags.with_dma = false,               // DMA feature is available on ESP target like ESP32-S3
	};

	led_indicator_strips_config_t strips_config = {
		.led_strip_cfg = strip_config,
		.led_strip_driver = LED_STRIP_RMT,
		.led_strip_rmt_cfg = rmt_config,
	};

	const led_indicator_config_t config = {
		.mode = LED_STRIPS_MODE,
		.led_indicator_strips_config = &strips_config,
		.blink_lists = my_led_mode,
		.blink_list_num = BLINK_MAX,
	};

	led_handle = led_indicator_create(&config);
	assert(led_handle != NULL);
	/* Force a deterministic OFF frame at boot to clear any random latched color. */
	led_indicator_set_rgb(led_handle, SET_RGB(0, 0, 0));
	vTaskDelay(pdMS_TO_TICKS(2));
	led_indicator_stop(led_handle, 0);
}


void set_identify_led_on(void)
{
	led_indicator_start(led_handle, 0);
}

void set_identify_led_off(void)
{
	led_indicator_stop(led_handle, 0);
	// 对于 WS2812, 这会发送一帧 0,0,0 的数据并触发 Reset 锁存
	led_indicator_set_rgb(led_handle, SET_RGB(0, 0, 0));
}

void set_identify_led_color(uint32_t color)
{
	my_blink_step[0].value = color;
}

void set_identify_led_time(uint32_t on_time, uint32_t off_time)
{
	my_blink_step[1].hold_time_ms = on_time;
	my_blink_step[2].hold_time_ms = off_time;
}

