/**
 * @file hal_thread.c
 * @brief HAL 线程实现（JieLi 平台）
 */

#include "hal_thread.h"
#include "hal_log.h"
#include "os/os_api.h"
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#define DEFAULT_STACK_SIZE  2048
#define DEFAULT_PRIORITY    15
#define DEFAULT_QUEUE_SIZE  32
#define TAG "HAL_THREAD"

typedef struct {
    char                       name[16];
    hal_thread_entry_t         entry;
    hal_thread_msg_handler_t   msg_handler;
    void                      *arg;
    void                      *user_ctx;
    uint32_t                   stack_size;
    uint8_t                    priority;
    uint16_t                   queue_size;
    volatile bool              running;
} hal_thread_impl_t;

/* Message IDs for internal control */
#define THREAD_MSG_EXIT  0x7FFF

static void thread_entry_wrapper(void *priv)
{
    hal_thread_impl_t *t = (hal_thread_impl_t *)priv;
    if (t && t->entry) {
        t->entry(t->arg);
    }
    /* Jieli RTOS: entry 返回前需调用 os_task_del_res(OS_TASK_SELF) 回收任务资源 */
    os_task_del_res(OS_TASK_SELF);
}

static void thread_msg_wrapper(void *priv)
{
    hal_thread_impl_t *t = (hal_thread_impl_t *)priv;
    /* 消息队列布局：msg[0]=类型, msg[1]=用户 msg_id, msg[2]=参数个数, msg[3..]=参数 */
    int msg[HAL_THREAD_MSG_PARAM_MAX + 3] = {0};
    int ret = 0;

    t->running = true;
    while (t->running) {
        ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
        if (ret != OS_TASKQ) {
            continue;
        }
        if (msg[0] != Q_MSG) {
            continue;
        }
        int msg_id      = msg[1];
        int param_count = msg[2];
        if (msg_id == THREAD_MSG_EXIT) {
            break;
        }
        if (t->msg_handler) {
            t->msg_handler(msg_id, &msg[3], param_count, t->user_ctx);
        }
    }
    t->running = false;
    /* 线程自删除以回收任务资源 */
    os_task_del_res(OS_TASK_SELF);
}

hal_thread_t hal_thread_create(const hal_thread_config_t *config)
{
    if (!config) {
        return NULL;
    }
    if (!config->entry && !config->msg_handler) {
        return NULL;
    }

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

    if (config->name) {
        strncpy(t->name, config->name, sizeof(t->name) - 1);
    } else {
        snprintf(t->name, sizeof(t->name), "hal_%p", t);
    }

    t->entry       = config->entry;
    t->msg_handler = config->msg_handler;
    t->arg         = config->arg;
    t->user_ctx    = config->user_ctx;
    t->stack_size  = config->stack_size ? config->stack_size : DEFAULT_STACK_SIZE;
    t->priority    = config->priority ? config->priority : DEFAULT_PRIORITY;
    t->queue_size  = config->queue_size ? config->queue_size : DEFAULT_QUEUE_SIZE;
    t->running     = true;

    int err = 0;
    if (t->entry) {
        err = os_task_create(thread_entry_wrapper, t,
                             t->priority, t->stack_size, t->queue_size, t->name);
    } else {
        err = os_task_create(thread_msg_wrapper, t,
                             t->priority, t->stack_size, t->queue_size, t->name);
    }

    if (err != OS_NO_ERR) {
        free(t);
        return NULL;
    }

    BD_LOGI(TAG, "hal_thread_create: name=%s, handle=%p, err=%d",
            t->name, t, err);
    return (hal_thread_t)t;
}

int hal_thread_post_msg(hal_thread_t thread, int msg_id, int argc, ...)
{
    if (!thread) {
        BD_LOGE(TAG, "post_msg: thread is NULL");
        return -1;
    }
    hal_thread_impl_t *t = (hal_thread_impl_t *)thread;
    if (!t->msg_handler) {
        BD_LOGE(TAG, "post_msg: no msg_handler");
        return -1;
    }
    if (!t->running) {
        BD_LOGE(TAG, "post_msg: thread not running");
        return -1;
    }
    if (argc < 0) {
        argc = 0;
    }
    if (argc > HAL_THREAD_MSG_PARAM_MAX) {
        argc = HAL_THREAD_MSG_PARAM_MAX;
    }

    /* os_taskq_post_msg 是可变参数，必须逐个展开 */
    int p[HAL_THREAD_MSG_PARAM_MAX] = {0};
    va_list ap;
    va_start(ap, argc);
    for (int i = 0; i < argc; i++) {
        p[i] = va_arg(ap, int);
    }
    va_end(ap);

    int ret = 0;
    switch (argc) {
    case 0:
        ret = os_taskq_post_msg(t->name, 2, msg_id, argc);
        break;
    case 1:
        ret = os_taskq_post_msg(t->name, 3, msg_id, argc, p[0]);
        break;
    case 2:
        ret = os_taskq_post_msg(t->name, 4, msg_id, argc, p[0], p[1]);
        break;
    case 3:
        ret = os_taskq_post_msg(t->name, 5, msg_id, argc, p[0], p[1], p[2]);
        break;
    default:
        ret = os_taskq_post_msg(t->name, 6, msg_id, argc, p[0], p[1], p[2], p[3]);
        break;
    }
    return (ret == OS_NO_ERR) ? 0 : -1;
}

void hal_thread_destroy(hal_thread_t thread)
{
    if (!thread) {
        return;
    }
    hal_thread_impl_t *t = (hal_thread_impl_t *)thread;

    if (t->msg_handler && t->running) {
        /* 通知消息线程退出，由其自身调用 os_task_del_res(OS_TASK_SELF) 自销毁 */
        os_taskq_post_msg(t->name, 2, THREAD_MSG_EXIT, 0);
        /* 等待线程实际退出（最多 ~500ms） */
        for (int i = 0; i < 50 && t->running; i++) {
            os_time_dly(1);
        }
    }
    /* 普通入口线程由入口函数返回后自行完成清理。 */
    free(t);
}

void hal_thread_sleep_ms(uint32_t ms)
{
    int ticks = ms / 10;
    if (ticks == 0 && ms > 0) {
        ticks = 1;
    }
    os_time_dly(ticks);
}
