/*
 * has_task_msg_manager/has_task_os_port.c
 *
 * Author: zhangzhaopeng
 * Version： 1.0
 * Created on : 2026-01-05
 * 系统适配层
 */
#include <stdint.h>
#include "has_task_msg_os_port.h"

// TODO: 信号量限制最大数量

#ifdef MSG_OPT_MUTEX_SEM
/**
 * @brief 互斥量初始化
 *
 * @param mutex:互斥量
 * @return 0:成功 -1：失败
 */
int msg_mutex_init(msg_mutex_t *mutex)
{
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
    if (pthread_mutex_init(mutex, NULL) != 0) {
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
	*mutex = xSemaphoreCreateMutex();
    if (*mutex == NULL) {
        msg_printf("create mutex err!!\n\n");
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
	*mutex = rt_mutex_create("has_msg", RT_IPC_FLAG_FIFO);
    if (*mutex == RT_NULL) {
        msg_printf("create mutex err!!\n\n");
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
    /* to be done */
    /* example:xr806 */
    if (OS_MutexCreate(mutex) != OS_OK) {
        msg_printf("create mutex err!!\n\n");
        return -1;
    }
    return 0;
#endif
}

/**
 * @brief 信号量初始化
 *
 * @param sem:信号量
 * @return 0:成功 -1：失败
 */
int msg_sem_init(msg_sem_t *sem)
{
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
    sem->poll_fd.fd =  eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK);
    if (sem->poll_fd.fd == -1) {
        msg_printf("create eventfd error!\n");
        return -1;
    }
    sem->poll_fd.events = POLLIN;  // 监控可读事件
    sem->poll_fd.revents = 0;
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
    *sem = xSemaphoreCreateCounting(UINT_MAX, 0);
    if (*sem == NULL) {
        msg_printf("create counting sem error!\n");
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
    *sem = rt_sem_create("has_sem", 0, RT_IPC_FLAG_FIFO);
    if (*sem == RT_NULL) {
        msg_printf("create counting sem error!\n");
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
    /* to be done */
    /* example:xr806 */
    if (OS_SemaphoreCreate(sem, 0, UINT_MAX) != OS_OK) {
        msg_printf("create counting sem error!\n");
        return -1;
    }
    return 0;
#endif
}

/**
 * @brief 消息通知
 *
 * @param sem:信号量
 * @return 0:成功 -1：失败
 */
int msg_sem_notify(msg_sem_t *sem)
{
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
    uint64_t val = 1;
    if (write(sem->poll_fd.fd, &val, sizeof(val)) != sizeof(val)) {
        msg_printf("notify thread err!\n");
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
    if (xSemaphoreGive(*sem) != pdTRUE) {
        msg_printf("notify thread err!\n");
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
    if (rt_sem_release(*sem) != RT_EOK) {
        msg_printf("notify thread err!\n");
        return -1;
    }
    return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
    /* to be done */
    /* example:xr806 */
    if (OS_SemaphoreRelease(sem) != OS_OK) {
        msg_printf("notify thread err!\n");
        return -1;
    }
    return 0;
#endif
}

/**
 * @brief 等待消息
 *
 * @param sem:信号量
 * @param ms_timeout:超时时间（ms）其中0：消息直接返回；-1：一直阻塞
 * @return MSG_WAIT_RET:
 * WAIT_FAIL = -1, 等待失败
 * WAIT_TIMEOUT = -1, 等待超时
 * WAIT_MSG_COME = -1, 有新消息
 */
enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout)
{
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
    uint64_t val;
    int ret = poll(&sem->poll_fd, 1, ms_timeout);
    if (ret == -1) {
        perror("poll fail\n");
        return WAIT_FAIL;
    } else if (ret == 0) {
        // msg_printf("poll timeout\n");
        return WAIT_TIMEOUT;
    }

    if (sem->poll_fd.revents & POLLIN) {
        if (read(sem->poll_fd.fd, &val, sizeof(val)) == sizeof(val)) { // 清零
            // msg_printf("read %ld\n", val);
            return WAIT_MSG_COME;
        }
        else {
            msg_printf("read error\n");
        }
    }

    // 检查错误事件
    msg_printf("something err happened,revents:%x\n", sem->poll_fd.revents);
    return WAIT_FAIL;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
    TickType_t xTicksToWait;
    if (ms_timeout < 0) {
        xTicksToWait = portMAX_DELAY;
    } else {
        xTicksToWait = pdMS_TO_TICKS(ms_timeout);
    }

    if (xSemaphoreTake(*sem, xTicksToWait) != pdTRUE) {
        // msg_printf("sem take fail\n");
        return WAIT_FAIL;
    }
    return WAIT_MSG_COME;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
    rt_err_t ret;
    rt_int32_t time;
    if (ms_timeout < 0) {
        time = RT_WAITING_FOREVER;
    } else {
        time = rt_tick_from_millisecond(ms_timeout);
    }

    ret = rt_sem_take(*sem, time);

    if (ret == RT_EOK) {
        return WAIT_MSG_COME;
    } else if (ret == (-RT_ETIMEOUT)) {
        return WAIT_TIMEOUT;
    } else {
        msg_printf("sem take fail\n");
        return WAIT_FAIL;
    }
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
    /* to be done */
    /* example:xr806 */
    OS_Time_t waitMS;
    if (ms_timeout < 0) {
        waitMS = OS_WAIT_FOREVER;
    } else {
        waitMS = (OS_Time_t)ms_timeout;
    }

    if (OS_SemaphoreWait(sem, waitMS) != OS_OK) {
        // msg_printf("sem take fail\n");
        return WAIT_FAIL;
    }
    return WAIT_MSG_COME;
#endif
}

#endif
