/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : bsp_key.c
  * @brief          : 板级支持包按键驱动实现
  ******************************************************************************
  */
/* USER CODE END Header */

#include "bsp_key.h"
#include "bsp_config.h"
#include "hal_gpio.h"
#include "bsp_board.h"
#include "bsp_board_manager.h"
#include "hal_delay.h"

/**
 * @brief 按键防抖配置
 */
#define KEY_DEBOUNCE_COUNT  5   /* Debounce count (each update is ~10ms, so 50ms debounce) */
#define KEY_LONG_PRESS_TIME  1000  /* Long press time in ms */
#define KEY_REPEAT_INTERVAL  200   /* Repeat interval in ms */
#define KEY_SHORT_PRESS_TIME  200   /* Short press time in ms */
#define KEY_UPDATE_INTERVAL  10    /* Update interval in ms */

/**
 * @brief 按键配置结构体
 */
typedef struct {
    hal_gpio_port_t port;
    hal_gpio_pin_t pin;
    uint8_t active_high;
} bsp_key_config_t;

/**
 * @brief 按键状态结构体，用于防抖和事件检测
 */
typedef struct {
    /* Debounce state */
    bsp_key_state_t current_state;     /* Current debounced state */
    bsp_key_state_t previous_state;    /* Previous debounced state */
    uint8_t debounce_counter;          /* Debounce counter */
    
    /* Event flags */
    uint8_t press_event;               /* Press event flag */
    uint8_t release_event;             /* Release event flag */
    uint8_t long_press_event;          /* Long press event flag */
    uint8_t repeat_event;              /* Repeat event flag */
    uint8_t short_press_event;         /* Short press event flag */
    
    /* Timing variables */
    uint32_t press_start_time;         /* Press start time in ms */
    uint32_t last_repeat_time;         /* Last repeat event time in ms */
    uint32_t current_time;             /* Current time in ms */
    
    /* Configuration */
    uint16_t long_press_time;          /* Long press time in ms */
    uint16_t repeat_interval;          /* Repeat interval in ms */
    uint16_t short_press_time;         /* Short press time in ms */
    
    /* Key configuration */
    const bsp_button_config_t* button_config;
} bsp_key_internal_state_t;

/**
 * @brief 按键状态表，用于防抖和事件检测
 */
static bsp_key_internal_state_t key_state_table[BSP_KEY_ID_MAX] = {0};

/**
 * @brief 获取当前板卡按键配置
 */
static const bsp_button_config_t* bsp_key_get_button_config(bsp_key_id_t key_id) {
    const bsp_board_config_t* board_config = bsp_board_get_config();
    if (board_config && key_id < board_config->buttons.count) {
        return &board_config->buttons.buttons[key_id];
    }
    return NULL;
}

/**
 * @brief 读取原始按键状态（无防抖）
 * @param key_id: 按键 ID
 * @retval 原始按键状态
 */
static bsp_key_state_t bsp_key_read_raw(bsp_key_id_t key_id) {
    bsp_key_state_t state;
    
    const bsp_button_config_t* button_config = bsp_key_get_button_config(key_id);
    if (button_config) {
        hal_gpio_pin_state_t gpio_state;
        
        /* Read GPIO pin state */
        gpio_state = hal_gpio_read_pin(button_config->port, button_config->pin);
        
        /* Convert to key state based on active level */
        if (button_config->active_high) {
            state = (gpio_state == HAL_GPIO_PIN_SET) ? BSP_KEY_STATE_PRESSED : BSP_KEY_STATE_RELEASED;
        } else {
            state = (gpio_state == HAL_GPIO_PIN_RESET) ? BSP_KEY_STATE_PRESSED : BSP_KEY_STATE_RELEASED;
        }
    } else {
        state = BSP_KEY_STATE_RELEASED;
    }
    
    return state;
}

/**
 * @brief 获取当前系统时间（毫秒）
 * @retval 当前时间（毫秒）
 */
static uint32_t bsp_key_get_time_ms(void) {
    /* Use HAL tick function */
    return hal_get_tick();
}

/**
 * @brief 初始化所有按键
 */
void bsp_key_init(void) {
    uint8_t i;
    
    /* Get current board configuration */
    const bsp_board_config_t* board_config = bsp_board_get_config();
    
    /* Initialize key state table */
    for (i = 0; i < BSP_KEY_ID_MAX; i++) {
        /* Get button configuration for this key */
        const bsp_button_config_t* button_config = bsp_key_get_button_config((bsp_key_id_t)i);
        
        /* Initialize with current state */
        key_state_table[i].current_state = bsp_key_read_raw((bsp_key_id_t)i);
        key_state_table[i].previous_state = key_state_table[i].current_state;
        key_state_table[i].debounce_counter = 0;
        
        /* Clear event flags */
        key_state_table[i].press_event = 0;
        key_state_table[i].release_event = 0;
        key_state_table[i].long_press_event = 0;
        key_state_table[i].repeat_event = 0;
        key_state_table[i].short_press_event = 0;
        
        /* Initialize timing variables */
        key_state_table[i].press_start_time = 0;
        key_state_table[i].last_repeat_time = 0;
        key_state_table[i].current_time = 0;
        
        /* Set default configuration */
        key_state_table[i].long_press_time = KEY_LONG_PRESS_TIME;
        key_state_table[i].repeat_interval = KEY_REPEAT_INTERVAL;
        key_state_table[i].short_press_time = KEY_SHORT_PRESS_TIME;
        
        /* Store button configuration */
        key_state_table[i].button_config = button_config;
    }
    
    /* Call board-specific button initialization if available */
    if (board_config && board_config->init_funcs.button_init) {
        board_config->init_funcs.button_init(&board_config->buttons);
    }
}

/**
 * @brief 更新按键状态（定期调用此函数，例如每 10ms）
 */
void bsp_key_update(void) {
    uint8_t i;
    uint32_t current_time = bsp_key_get_time_ms();
    
    for (i = 0; i < BSP_KEY_ID_MAX; i++) {
        /* Skip if button configuration is not available */
        if (!key_state_table[i].button_config) {
            continue;
        }
        
        bsp_key_state_t raw_state = bsp_key_read_raw((bsp_key_id_t)i);
        bsp_key_internal_state_t* key_state = &key_state_table[i];
        
        /* Update current time */
        key_state->current_time = current_time;
        
        /* Debounce logic - optimized version */
        if (raw_state != key_state->current_state) {
            /* State is changing, increment counter */
            if (++key_state->debounce_counter >= KEY_DEBOUNCE_COUNT) {
                /* Debounce count reached, update state */
                key_state->previous_state = key_state->current_state;
                key_state->current_state = raw_state;
                key_state->debounce_counter = 0;
                
                if (raw_state == BSP_KEY_STATE_PRESSED) {
                    /* Key pressed event */
                    key_state->press_event = 1;
                    key_state->release_event = 0;
                    key_state->short_press_event = 0;
                    
                    /* Reset timing variables */
                    key_state->press_start_time = current_time;
                    key_state->last_repeat_time = current_time;
                    key_state->long_press_event = 0;
                    key_state->repeat_event = 0;
                } else {
                    /* Key released event */
                    key_state->release_event = 1;
                    key_state->press_event = 0;
                    
                    /* Check for short press event */
                    uint32_t press_duration = current_time - key_state->press_start_time;
                    if (press_duration < key_state->long_press_time) {
                        key_state->short_press_event = 1;
                    }
                    
                    /* Reset long press and repeat flags */
                    key_state->long_press_event = 0;
                    key_state->repeat_event = 0;
                }
            }
        } else {
            /* State is stable, reset counter */
            key_state->debounce_counter = 0;
            
            /* Handle timing-based events if key is pressed */
            if (raw_state == BSP_KEY_STATE_PRESSED) {
                uint32_t press_duration = current_time - key_state->press_start_time;
                
                /* Check for long press event - only set once */
                if (press_duration >= key_state->long_press_time && !key_state->long_press_event) {
                    key_state->long_press_event = 1;
                }
                
                /* Check for repeat event - only after long press */
                if (key_state->long_press_event && 
                    (current_time - key_state->last_repeat_time >= key_state->repeat_interval)) {
                    key_state->repeat_event = 1;
                    key_state->last_repeat_time = current_time;
                }
            }
        }
    }
}

/**
 * @brief 读取防抖后的按键状态
 * @param key_id: 按键 ID
 * @retval 按键状态
 */
bsp_key_state_t bsp_key_read(bsp_key_id_t key_id) {
    if (key_id < BSP_KEY_ID_MAX) {
        return key_state_table[key_id].current_state;
    }
    return BSP_KEY_STATE_RELEASED;
}

/**
 * @brief 检查按键是否按下
 * @param key_id: 按键 ID
 * @retval 按下返回 1，否则返回 0
 */
uint8_t bsp_key_is_pressed(bsp_key_id_t key_id) {
    return (bsp_key_read(key_id) == BSP_KEY_STATE_PRESSED) ? 1 : 0;
}

/**
 * @brief 检查按键是否释放
 * @param key_id: 按键 ID
 * @retval 释放返回 1，否则返回 0
 */
uint8_t bsp_key_is_released(bsp_key_id_t key_id) {
    return (bsp_key_read(key_id) == BSP_KEY_STATE_RELEASED) ? 1 : 0;
}

/**
 * @brief 检查按键按下事件（边沿检测）
 * @param key_id: 按键 ID
 * @retval 按下事件返回 1，否则返回 0
 */
uint8_t bsp_key_get_press_event(bsp_key_id_t key_id) {
    uint8_t event = 0;
    
    if (key_id < BSP_KEY_ID_MAX) {
        event = key_state_table[key_id].press_event;
        key_state_table[key_id].press_event = 0;  /* Clear event flag */
    }
    
    return event;
}

/**
 * @brief 检查按键释放事件（边沿检测）
 * @param key_id: 按键 ID
 * @retval 释放事件返回 1，否则返回 0
 */
uint8_t bsp_key_get_release_event(bsp_key_id_t key_id) {
    uint8_t event = 0;
    
    if (key_id < BSP_KEY_ID_MAX) {
        event = key_state_table[key_id].release_event;
        key_state_table[key_id].release_event = 0;  /* Clear event flag */
    }
    
    return event;
}

/**
 * @brief 检查按键长按事件
 * @param key_id: 按键 ID
 * @retval 长按事件返回 1，否则返回 0
 */
uint8_t bsp_key_get_long_press_event(bsp_key_id_t key_id) {
    uint8_t event = 0;
    
    if (key_id < BSP_KEY_ID_MAX) {
        event = key_state_table[key_id].long_press_event;
        /* Long press event is only reported once */
    }
    
    return event;
}

/**
 * @brief 检查按键重复事件
 * @param key_id: 按键 ID
 * @retval 重复事件返回 1，否则返回 0
 */
uint8_t bsp_key_get_repeat_event(bsp_key_id_t key_id) {
    uint8_t event = 0;
    
    if (key_id < BSP_KEY_ID_MAX) {
        event = key_state_table[key_id].repeat_event;
        key_state_table[key_id].repeat_event = 0;  /* Clear event flag */
    }
    
    return event;
}

/**
 * @brief 检查按键短按事件
 * @param key_id: 按键 ID
 * @retval 短按事件返回 1，否则返回 0
 */
uint8_t bsp_key_get_short_press_event(bsp_key_id_t key_id) {
    uint8_t event = 0;
    
    if (key_id < BSP_KEY_ID_MAX) {
        event = key_state_table[key_id].short_press_event;
        key_state_table[key_id].short_press_event = 0;  /* Clear event flag */
    }
    
    return event;
}
