#include "Int_Key.h"
#include <stddef.h>

/* 单个按键扫描上下文：
 * raw_level    原始采样电平
 * stable_level 去抖后的稳定电平
 * long_started 是否已上报过长按开始事件
 */
typedef struct
{
    GPIO_TypeDef *port;
    uint16_t pin;
    Key_t key;
    uint8_t stable_level;
    uint8_t raw_level;
    uint8_t long_started;
    uint32_t last_change_ms;
    uint32_t press_ms;
} KeyScanCtx_t;

#define KEY_COUNT (5u)
#define KEY_SCAN_PERIOD_MS (5u)
#define KEY_DEBOUNCE_MS (20u)
#define KEY_LONG_MS (400u)
#define KEY_QUEUE_SIZE (12u)

static KeyScanCtx_t s_keys[KEY_COUNT] = {
    {KEY1_GPIO_Port, KEY1_Pin, KEY_1, 1u, 1u, 0u, 0u, 0u},
    {KEY2_GPIO_Port, KEY2_Pin, KEY_2, 1u, 1u, 0u, 0u, 0u},
    {KEY3_GPIO_Port, KEY3_Pin, KEY_3, 1u, 1u, 0u, 0u, 0u},
    {KEY4_GPIO_Port, KEY4_Pin, KEY_4, 1u, 1u, 0u, 0u, 0u},
    {KEY5_GPIO_Port, KEY5_Pin, KEY_5, 1u, 1u, 0u, 0u, 0u},
};

static KeyAction_t s_queue[KEY_QUEUE_SIZE];
static uint8_t s_q_head = 0u;
static uint8_t s_q_tail = 0u;
static uint32_t s_last_scan_ms = 0u;

static uint8_t queue_next(uint8_t v)
{
    /* 环形队列下标递增。 */
    v++;
    if (v >= KEY_QUEUE_SIZE)
    {
        v = 0u;
    }
    return v;
}

static void push_action(Key_t key, KeyEvt_t evt)
{
    /* 队列满时丢弃新事件，避免阻塞主循环。 */
    uint8_t next = queue_next(s_q_head);
    if (next == s_q_tail)
    {
        return;
    }
    s_queue[s_q_head].key = key;
    s_queue[s_q_head].evt = evt;
    s_q_head = next;
}

void Int_Key_Task(void)
{
    uint32_t now = HAL_GetTick();
    /* 固定周期扫描，避免过高频率浪费CPU。 */
    if ((uint32_t)(now - s_last_scan_ms) < KEY_SCAN_PERIOD_MS)
    {
        return;
    }
    s_last_scan_ms = now;

    for (uint8_t i = 0u; i < KEY_COUNT; i++)
    {
        KeyScanCtx_t *k = &s_keys[i];
        uint8_t raw = (HAL_GPIO_ReadPin(k->port, k->pin) == GPIO_PIN_RESET) ? 0u : 1u;

        if (raw != k->raw_level)
        {
            k->raw_level = raw;
            k->last_change_ms = now;
        }

        if ((uint32_t)(now - k->last_change_ms) >= KEY_DEBOUNCE_MS)
        {
            if (k->stable_level != k->raw_level)
            {
                k->stable_level = k->raw_level;

                if (k->stable_level == 0u)
                {
                    /* 稳定按下：记录按下时间，等待长按判断。 */
                    k->press_ms = now;
                    k->long_started = 0u;
                }
                else
                {
                    /* 稳定释放：若未触发长按则上报CLICK，否则上报RELEASE。 */
                    push_action(k->key, k->long_started ? KEY_EVT_RELEASE : KEY_EVT_CLICK);
                }
            }
        }

        if (k->stable_level == 0u)
        {
            uint32_t hold_ms = (uint32_t)(now - k->press_ms);
            if (hold_ms >= KEY_LONG_MS)
            {
                if (k->long_started == 0u)
                {
                    /* 长按开始事件只上报一次。 */
                    k->long_started = 1u;
                    push_action(k->key, KEY_EVT_LONG_START);
                }
            }
        }
    }
}

bool Int_Key_PopAction(KeyAction_t *action)
{
    /* 从事件队列弹出一个事件供上层消费。 */
    if (action == NULL)
    {
        return false;
    }

    if (s_q_tail == s_q_head)
    {
        return false;
    }

    *action = s_queue[s_q_tail];
    s_q_tail = queue_next(s_q_tail);
    return true;
}

Key_t Int_key_read(void)
{
    /* 兼容旧接口：仅返回按键编号，不区分事件类型。 */
    KeyAction_t action;
    if (Int_Key_PopAction(&action))
    {
        return action.key;
    }
    return KEY_NONE;
}
