#ifndef HW_LIB_SIM_KEY_H
#define HW_LIB_KEY_H
#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#define KEY_TICKS_INTERVAL    5    // 定时器间隔时间，单位为毫秒
#define DEBOUNCE_TICKS    0    // 按键去抖动计数阈值，最大为7（0 ~ 7）
#define SHORT_TICKS       (300 / KEY_TICKS_INTERVAL)  // 短按阈值，单位为定时器间隔的倍数
#define LONG_TICKS        (1000 / KEY_TICKS_INTERVAL)  // 长按阈值，单位为定时器间隔的倍数
#define KEY_STOP_FREE     1    // 按键停止释放状态标识


typedef struct Key_List Key_t;  // 定义结构体Key_t为Key_List的别名
typedef void (*Key_Callback_t)(Key_t *key);  // 定义函数指针类型Key_Callback_t，接受一个Key_t结构体指针参数

typedef enum {
    KEY_PRESS_DOWN = 0,  // 按下事件
    KEY_PRESS_UP,        // 弹起事件
    KEY_PRESS_REPEAT,    // 重复按下事件
    KEY_SINGLE_CLICK,    // 单击事件
    KEY_DOUBLE_CLICK,    // 双击事件
    KEY_LONG_PRESS_START,  // 长按开始事件
    KEY_LONG_PRESS_HOLD,   // 长按保持事件
    number_of_event,   // 事件总数
    KEY_ALL_EVENT,         // 所有事件
    NONE_PRESS         // 无按键事件
} PressEvent;  // 定义枚举类型PressEvent，表示按键事件类型

struct Key_List {
    Key_t *next;         // 指向下一个按键结构体的指针
    uint16_t ticks;       // 计时器
    uint8_t repeat: 4;   // 按键重复次数，占4位
    uint8_t event: 4;   // 当前按键事件类型，占4位
    uint8_t state: 3;   // 按键状态，占3位
    uint8_t debounce_cnt: 3;  // 按键去抖计数，占3位
    uint8_t active_level: 1;  // 按键激活电平，占1位
    uint8_t key_level: 1;     // 当前按键电平，占1位
    uint8_t key_id;            // 按键ID
    uint8_t (*hal_read_pin)(uint8_t key_id_);  // 函数指针，用于获取按键电平
    Key_Callback_t cb[number_of_event];  // 按键事件回调函数数组
};

/**
 * @brief   初始化按键结构体
 * @param   key: [输入]           按键结构体指针
 * @param   key_id: [输入]        按键ID
 * @param   active_level: [输入]  激活电平
 * @param   read_pin: [输入]      读取按键状态的函数指针
 * @return  void
 * @example key_init(&my_key, 1, ACTIVE_HIGH, read_key_pin_func);
**/
void key_init(Key_t *key, uint8_t key_id, uint8_t active_level, uint8_t(*read_pin)(uint8_t));

/**
 * @brief   为按键设置回调函数
 * @param   key: [输入]       按键结构体指针
 * @param   event: [输入]     按键事件类型
 * @param   cb: [输入]        回调函数指针
 * @param   start: [输入]     是否立即启用
 * @return  void
 * @example key_attach(&my_key, PRESS_EVENT_LONG_PRESS, key_callback_func, true);
**/
void key_attach(Key_t *key, PressEvent event, Key_Callback_t cb, bool start);

/**
 * @brief   获取按键当前事件
 * @param   key: [输入]     指向按键结构体的指针
 * @return  当前按键事件
 * @example PressEvent current_event = get_key_event(&my_key);
 */
PressEvent get_key_event(Key_t *key);

/**
 * @brief   启动按键检测
 * @param   key: [输入]     指向按键结构体的指针
 * @return  错误码，0表示成功
 * @example int result = key_start(&my_key);
 */
int key_start(Key_t *key);

/**
 * @brief   停止按键检测
 * @param   key: [输入]     指向按键结构体的指针
 * @return  void
 * @example key_stop(&my_key);
 */
void key_stop(Key_t *key);

/**
 * @brief   按键定时处理函数
 * @return  void
 * @example key_ticks();
 */
void key_ticks(void);

#ifdef __cplusplus
}
#endif
#endif //HW_LIB_SIM_KEY_H
