/**
 * @file hal_timer.c
 * @brief HAL 定时器实现（JieLi 平台）
 */

#include "hal_timer.h"
#include "system/includes.h"
#include <stdlib.h>

typedef struct {
    hal_timer_cb_t  callback;
    void           *user_ctx;
    u16             timer_id;
    bool            repeat;
    bool            running;
} hal_timer_impl_t;

static void timer_callback_wrapper(void *priv)
{
    hal_timer_impl_t *t = (hal_timer_impl_t *)priv;
    if (!t) {
        return;
    }
    if (!t->repeat) {
        t->running = false;
        t->timer_id = 0;
    }
    if (t->callback) {
        t->callback(t->user_ctx);
    }
}

hal_timer_t hal_timer_create(hal_timer_cb_t callback, void *user_ctx)
{
    if (!callback) {
        return NULL;
    }

    hal_timer_impl_t *t = (hal_timer_impl_t *)zalloc(sizeof(hal_timer_impl_t));
    if (!t) {
        return NULL;
    }

    t->callback = callback;
    t->user_ctx = user_ctx;
    t->timer_id = 0;
    t->repeat   = false;
    t->running  = false;

    return (hal_timer_t)t;
}

int hal_timer_start(hal_timer_t timer, uint32_t interval_ms, bool repeat)
{
    if (!timer) {
        return -1;
    }
    hal_timer_impl_t *t = (hal_timer_impl_t *)timer;

    /* 若定时器正在运行则先停止 */
    if (t->running && t->timer_id) {
        if (t->repeat) {
            sys_timer_del(t->timer_id);
        } else {
            sys_timeout_del(t->timer_id);
        }
        t->timer_id = 0;
        t->running = false;
    }

    t->repeat = repeat;
    if (repeat) {
        t->timer_id = sys_timer_add(t, timer_callback_wrapper, interval_ms);
    } else {
        t->timer_id = sys_timeout_add(t, timer_callback_wrapper, interval_ms);
    }

    if (t->timer_id == 0) {
        return -1;
    }
    t->running = true;
    return 0;
}

int hal_timer_stop(hal_timer_t timer)
{
    if (!timer) {
        return -1;
    }
    hal_timer_impl_t *t = (hal_timer_impl_t *)timer;

    if (!t->running || !t->timer_id) {
        return 0;
    }

    if (t->repeat) {
        sys_timer_del(t->timer_id);
    } else {
        sys_timeout_del(t->timer_id);
    }
    t->timer_id = 0;
    t->running = false;
    return 0;
}

void hal_timer_destroy(hal_timer_t timer)
{
    if (!timer) {
        return;
    }
    hal_timer_stop(timer);
    free(timer);
}
