/**
 * @file led_control.c
 * @brief LED控制API实现 (基于HTR3236)
 * @version 1.0
 */

#include "led_control.h"
#include <string.h>
#include <math.h>
#include <timer.h>

/*=========================================================================
    内部函数
    -----------------------------------------------------------------------*/

/**
 * @brief 检查LED ID是否有效
 */
static int is_valid_led(led_id_t led)
{
    return (led >= 1 && led <= 36 && led != 36);  // OUT36未使用
}

/**
 * @brief 获取LED组起始和结束索引
 */
static void get_group_range(led_group_t group, uint8_t *start, uint8_t *end)
{
    switch (group) {
        case LED_GROUP_L_SERIES:
            *start = LED_L1;
            *end = LED_L15;
            break;
        case LED_GROUP_D_SERIES:
            *start = LED_D1;
            *end = LED_D15;
            break;
        // case LED_GROUP_FUNCTION:
        //     *start = LED_ANC;
        //     *end = LED_GAME_MODE;
        //     break;
        case LED_GROUP_ALL:
        default:
            *start = 1;
            *end = 35;  // 排除OUT36
            break;
    }
}

/*=========================================================================
    LED物理映射表
    -----------------------------------------------------------------------*/
// 根据测试结果：LED_L1-L15的实际OUT口
const uint8_t led_l_physical_map[15] = {
    15,  // LED_L1  -> OUT15 
    14,  // LED_L2  -> OUT14  
    13,  // LED_L3  -> OUT13  
    11,  // LED_L4  -> OUT11  
    10,  // LED_L5  -> OUT10
    9,   // LED_L6 -> OUT9   
    8,   // LED_L7 -> OUT8   
    7,   // LED_L8 -> OUT7   
    6,   // LED_L9 -> OUT6   
    5,   // LED_L10 -> OUT5   
    4,   // LED_L11 -> OUT4   
    12,  // LED_L12  -> OUT12 *
    18,  // LED_L13  -> OUT18 *
    17,  // LED_L14  -> OUT17 
    16,  // LED_L15  -> OUT16 
};
// 根据测试结果：LED_D1-D15的实际OUT口
const uint8_t led_d_physical_map[15] = {
    21,  // LED_D1 -> OUT21  
    20,  // LED_D2 -> OUT20  
    19,  // LED_D3 -> OUT19  
    26,  // LED_D4 -> OUT26 *
    33,  // LED_D5  -> OUT33 *
    32,  // LED_D6  -> OUT32 
    31,  // LED_D7  -> OUT31  
    30,  // LED_D8  -> OUT30  
    29,  // LED_D9  -> OUT29  
    28,  // LED_D10 -> OUT28  
    27,  // LED_D11 -> OUT27  
    25,  // LED_D12 -> OUT25 
    24,  // LED_D13 -> OUT24  
    23,  // LED_D14 -> OUT23  
    22,  // LED_D15 -> OUT22  
};

const uint8_t mic_gain_to_led[39] = {
    0,  // [-1] 增益-1: 0个LED，这个设计未启用
    1,  // [0] 增益0: 0个LED
    1,  // [1] 增益1: 0个LED
    1,  // [2] 增益2: 0个LED
    1,  // [3] 增益3: 1个LED
    2,  // [4] 增益4: 1个LED
    2,  // [5] 增益5: 1个LED
    2,  // [6] 增益6: 2个LED
    2,  // [7] 增益7: 2个LED
    3,  // [8] 增益8: 2个LED
    3,  // [9] 增益9: 3个LED
    3,  // [10] 增益10: 3个LED
    3,  // [11] 增益11: 3个LED
    4,  // [12] 增益12: 4个LED
    4,  // [13] 增益13: 4个LED
    4,  // [14] 增益14: 4个LED
    5,  // [15] 增益15: 5个LED
    5,  // [16] 增益16: 5个LED
    6,  // [17] 增益17: 6个LED
    6,  // [18] 增益18: 6个LED
    7,  // [19] 增益19: 7个LED
    7,  // [20] 增益20: 7个LED
    8,  // [21] 增益21: 8个LED
    8,  // [22] 增益22: 8个LED
    9,  // [23] 增益23: 9个LED
    9,  // [24] 增益24: 9个LED
    10, // [25] 增益25: 10个LED
    10, // [26] 增益26: 10个LED
    11, // [27] 增益27: 11个LED
    11, // [28] 增益28: 11个LED
    12, // [29] 增益29: 12个LED
    12, // [30] 增益30: 12个LED
    13, // [31] 增益31: 13个LED
    13, // [32] 增益32: 13个LED
    14, // [33] 增益33: 14个LED
    14, // [34] 增益34: 14个LED
    15, // [35] 增益35: 15个LED
    15, // [36] 增益36: 15个LED
    15  // [37] 增益36+1.5 digitial gain: 15个LED
};

// DAC监听音量增益到LED数量的映射表
// 索引 0 = 静音 (0个LED, reg 0x0034=0x0000)
// 索引 1~29: -28dB ~ 0dB，1dB/步，每2个dB对应1个LED（最后1dB独占15号LED）
const uint8_t dac_gain_to_led[30] = {
    0,  // [0]  mute:  0 LEDs
    1,  // [1]  -28dB: 1 LED
    1,  // [2]  -27dB: 1 LED
    2,  // [3]  -26dB: 2 LEDs
    2,  // [4]  -25dB: 2 LEDs
    3,  // [5]  -24dB: 3 LEDs
    3,  // [6]  -23dB: 3 LEDs
    4,  // [7]  -22dB: 4 LEDs
    4,  // [8]  -21dB: 4 LEDs
    5,  // [9]  -20dB: 5 LEDs
    5,  // [10] -19dB: 5 LEDs
    6,  // [11] -18dB: 6 LEDs
    6,  // [12] -17dB: 6 LEDs
    7,  // [13] -16dB: 7 LEDs
    7,  // [14] -15dB: 7 LEDs
    8,  // [15] -14dB: 8 LEDs
    8,  // [16] -13dB: 8 LEDs
    9,  // [17] -12dB: 9 LEDs
    9,  // [18] -11dB: 9 LEDs
    10, // [19] -10dB: 10 LEDs
    10, // [20]  -9dB: 10 LEDs
    11, // [21]  -8dB: 11 LEDs
    11, // [22]  -7dB: 11 LEDs
    12, // [23]  -6dB: 12 LEDs
    12, // [24]  -5dB: 12 LEDs
    13, // [25]  -4dB: 13 LEDs
    13, // [26]  -3dB: 13 LEDs
    14, // [27]  -2dB: 14 LEDs
    14, // [28]  -1dB: 14 LEDs
    15, // [29]   0dB: 15 LEDs
};

/*=========================================================================
    内部函数 - 获取实际OUT口
    -----------------------------------------------------------------------*/
static uint8_t get_physical_out(led_id_t led)
{
    // 如果是L系列LED
    if (led >= LED_L1 && led <= LED_L15) {
        uint8_t index = led - LED_L1;
        return led_l_physical_map[index];
    }
    else if (led >= LED_D1 && led <= LED_D15) {
        uint8_t index = led - LED_D1;
        return led_d_physical_map[index];
    }
    
    // 其他LED直接返回原值
    return (uint8_t)led;
}

/*=========================================================================
    基础控制API实现
    -----------------------------------------------------------------------*/

void led_control_init(led_control_t *ctx,
                      htr3236_t *dev,
                      CLIENT_INTERFACE(i2c_master_if,i2c))
{
    ctx->htr3236_dev = dev;
    ctx->i2c = i2c;
    
    // 初始化亮度缓存
    memset(ctx->brightness, 0, sizeof(ctx->brightness));
    
    // 配置所有LED通道的电流 (使用IMAX/2)
    for (int led = 1; led <= 35; led++) {  // 跳过OUT36
        htr3236_set_led_config(ctx->htr3236_dev,  ctx->i2c,
                               led, HTR3236_CURRENT_HALF, 1);
    }
    
    // 初始关闭所有LED
    for (int led = 1; led <= 35; led++) {
        htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, 0);
    }
    
    htr3236_update(ctx->htr3236_dev, ctx->i2c);
}

int led_set_brightness(led_control_t *ctx,
                       led_id_t led,
                       uint8_t brightness)
{
    if (!is_valid_led(led)) {
        return -1;
    }
    
    ctx->brightness[led - 1] = brightness;
    return htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness);
}

int led_on(led_control_t *ctx, led_id_t led)
{
    return led_set_brightness(ctx, led, 30/*255*/);
}

int led_off(led_control_t *ctx, led_id_t led)
{
    return led_set_brightness(ctx, led, 0);
}

int led_toggle(led_control_t *ctx, led_id_t led)
{
    if (!is_valid_led(led)) {
        return -1;
    }
    
    uint8_t new_brightness = (ctx->brightness[led - 1] == 0) ? 255 : 0;
    return led_set_brightness(ctx, led, new_brightness);
}

int led_update_all(led_control_t *ctx)
{
    return htr3236_update(ctx->htr3236_dev, ctx->i2c);
}

/*=========================================================================
    组控制API实现
    -----------------------------------------------------------------------*/

int led_group_set_brightness(led_control_t *ctx,
                             led_group_t group,
                             uint8_t brightness)
{
    uint8_t start, end;
    get_group_range(group, &start, &end);

    if (group == LED_GROUP_FUNCTION) {
        // 功能LED需要单独处理每个LED
        led_id_t function_leds[] = {
            LED_MUSIC, LED_ANC, LED_FOOTSTEP_MODE, LED_AI7_1, LED_GAME_MODE
        };
        
        for (int i = 0; i < 5; i++) {
            led_id_t led = function_leds[i];
            uint8_t physical_out = get_physical_out(led);  // 如果有映射
            ctx->brightness[physical_out - 1] = brightness;
            htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness);
        }
    }
    else
    {
        for (uint8_t led = start; led <= end; led++) {
            if (led == 36) continue;  // 跳过未使用的OUT36
            if((group == LED_GROUP_L_SERIES) || (group == LED_GROUP_D_SERIES))
            {
                uint8_t physical_out = get_physical_out(led);
                ctx->brightness[physical_out - 1] = brightness;
            }
            else ctx->brightness[led - 1] = brightness;
            htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness);
        }
    }
    
    return htr3236_update(ctx->htr3236_dev, ctx->i2c);
}

int led_group_on(led_control_t *ctx, led_group_t group)
{
    return led_group_set_brightness(ctx, group, 255);
}

int led_group_off(led_control_t *ctx, led_group_t group)
{
    return led_group_set_brightness(ctx, group, 0);
}