#include "led_strip.h"

rmt_channel_handle_t led_chan = NULL;
rmt_encoder_handle_t led_encoder = NULL;
rmt_transmit_config_t tx_config = {
    .loop_count = 0, // no transfer loop
};

static uint8_t led_strip_pixels[EXAMPLE_LED_NUMBERS * 3];
uint16_t toggle_cycle = 1000;
bool toggle_flag = true;
static uint8_t rgb_color_index = RGB_COLOR_RAD;

rgb_color_t rgb_color_rad = {0,255,0,0,0,1,0};
rgb_color_t rgb_color_orange = {0,255,80,0,0,1,0};
rgb_color_t rgb_color_green = {0,0,255,0,0,1,0};
rgb_color_t rgb_color_blue = {0,0,0,255,0,1,0};
rgb_color_t rgb_color_cyan = {0,0,255,255,0,1,0};
rgb_color_t rgb_color_purple = {0,255,0,255,0,1,0};
rgb_color_t rgb_color_white = {0,255,255,255,0,1,0};
rgb_color_t rgb_color_green_white = {0,0,255,0,0,2,5};
rgb_color_t rgb_color_green_purple = {0,0,255,0,0,2,5};
void led_strip_init(void)
{
    
    // ESP_LOGI(TAG, "Create RMT TX channel");
    
    rmt_tx_channel_config_t tx_chan_config = {
        .clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
        .gpio_num = RMT_LED_STRIP_GPIO_NUM,
        .mem_block_symbols = 64, // increase the block size can make the LED less flickering
        .resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ,
        .trans_queue_depth = 4, // set the number of transactions that can be pending in the background
    };
    ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan));

    // ESP_LOGI(TAG, "Install led strip encoder");
    
    led_strip_encoder_config_t encoder_config = {
        .resolution = RMT_LED_STRIP_RESOLUTION_HZ,
    };
    ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder));

    // ESP_LOGI(TAG, "Enable RMT TX channel");
    ESP_ERROR_CHECK(rmt_enable(led_chan));

    // ESP_LOGI(TAG, "Start LED rainbow chase");
    

}
void led_strip_set_pixel(uint8_t pin, uint8_t index, uint8_t green, uint8_t blue, uint8_t red)
{
    led_strip_pixels[0 + index * 3] = green;
    led_strip_pixels[1 + index * 3] = red;
    led_strip_pixels[2 + index * 3] = blue;
    ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
    ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
}

void work_rgb_led_start(void)
{
    led_strip_init();
    /* 创建 shell 的接收任务 _work_sh() */
    static os_work_t work_handler_rgb_led;
    os_work_create(&work_handler_rgb_led, "work-rgb-led", _work_rgb_led, NULL, OS_PRIORITY_NORMAL);
    os_work_submit(default_os_work_q_hdl, &work_handler_rgb_led, toggle_cycle * 0.5);

}

void _work_rgb_led(void *arg)
{
    static rgb_color_t* expression;
    static uint8_t rgb_color_index_lat = 255;
    if(rgb_color_index_lat != rgb_color_index)
    {
        rgb_color_index_lat = rgb_color_index;
        switch (rgb_color_index)
        {
            case RGB_COLOR_RAD:
                expression = &rgb_color_rad;
                break;
            case RGB_COLOR_ORANGE:
                expression = &rgb_color_orange;
                break;
            case RGB_COLOR_GREEN:
                expression = &rgb_color_green;
                break;
            case RGB_COLOR_WHITE:
                expression = &rgb_color_white;
                break;
            case RGB_COLOR_PURPLE:
                expression = &rgb_color_purple;
                break;
            case RGB_COLOR_CYAN:
                expression = &rgb_color_cyan;
                break;
            case RGB_COLOR_BLUE:
                expression = &rgb_color_blue;
                break;
            case RGB_COLOR_GREEN_WHITE:
                expression = &rgb_color_green_white;
                break;
            case RGB_COLOR_GREEN_PURPLE:
                expression = &rgb_color_green_purple;
                break;
            default:
                break;
        }
    }
    
    rgb_toggle(expression);
    os_work_later(toggle_cycle * 0.5);
}

void rgb_update_cyle(uint16_t cyle)
{
    toggle_flag = (cyle == 888 ?  false : true);
    
    toggle_cycle = cyle;
}
uint8_t breathing_dispose(rgb_color_t* rgb_color,int16_t* vel, uint8_t color_min, uint8_t color_max)
{
    static int dir = 1, color_dir = 1, color_cnt = 0;
    *vel += dir * rgb_color->colortoggle_speed;
    if(*vel > color_max){*vel = color_max; dir = -1;}
    else if(*vel < color_min){*vel = color_min; dir = 1; color_cnt += color_dir;}
    
    if(color_cnt >= rgb_color->color_cnt -1 )
        color_dir = -1;
    else if(color_cnt <= 0)
        color_dir = 1;

    return color_cnt;
}
void breathing_color_change(rgb_color_t* rgb_color)
{
    static int16_t COLOR_SUM;
    uint8_t color_cnt = breathing_dispose(rgb_color, &COLOR_SUM, 0, 255);
    switch (rgb_color_index)
    {
        case RGB_COLOR_GREEN_WHITE:
        {
            switch(color_cnt)
            {
                case 0:
                {
                    rgb_color->red = 0;
                    rgb_color->green = (uint8_t)COLOR_SUM;
                    rgb_color->blue = 0;
                    break;
                }   
                case 1:
                {
                    rgb_color->red = (uint8_t)COLOR_SUM;
                    rgb_color->green = (uint8_t)COLOR_SUM;
                    rgb_color->blue = (uint8_t)COLOR_SUM;
                    break;
                }
            }
            break;
        }
        case  RGB_COLOR_GREEN_PURPLE:
        {
            switch(color_cnt)
            {
                case 0:
                {
                    rgb_color->red = 0;
                    rgb_color->green = (uint8_t)COLOR_SUM;
                    rgb_color->blue = 0;
                    break;
                }
                case 1:
                {
                    rgb_color->red = (uint8_t)COLOR_SUM;
                    rgb_color->green = 0;
                    rgb_color->blue = (uint8_t)COLOR_SUM;
                    break;
                }
            }
            break;
        }
        
        default:
            break;
    }
}
void rgb_toggle(rgb_color_t* rgb_color)
{
    if(rgb_color->color_cnt > 1)
    {
        breathing_color_change(rgb_color);
        led_strip_set_pixel(0,rgb_color->index,rgb_color->green,rgb_color->blue,rgb_color->red);
        return;
    }
    if(rgb_color->toggle_flag == 0)
        led_strip_set_pixel(0,rgb_color->index,rgb_color->green,rgb_color->blue,rgb_color->red);
    else
        led_strip_set_pixel(0,rgb_color->index,0,0,0);

    if(toggle_flag == true)     
        rgb_color->toggle_flag = !rgb_color->toggle_flag;
}

void rgb_color_change(uint8_t index, uint8_t color)
{
    rgb_color_index = color;
}