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

#include <stdint.h>
#include <string.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_key_Level)(uint8_t key_id_);  // 函数指针,用于获取按键电平
    Key_Callback_t cb[number_of_event];  // 按键事件回调函数数组
};

/**
 * @brief   初始化按键模块
 * @param   key: [输入]     指向按键结构体的指针
 * @param   pin_level: [输入]     获取按键电平的回调函数
 * @param   active_level: [输入]    激活电平
 * @param   key_id: [输入]    按键ID
 * @return  void
 * @example key_init(&my_key, get_pin_level, ACTIVE_HIGH, 1);
 */
void key_init(Key_t *key, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t key_id);

/**
 * @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