#ifndef HAS_TASK_MSG_OS_PROT_H
#define HAS_TASK_MSG_OS_PROT_H

#define MSG_OPT_OS_LINUX 1
#define MSG_OPT_OS_freeRTOS 2
#define MSG_OPT_OS_RT_THREAD 3
#define MSG_OPT_OS_NONE_OR_OSAL 4
#define MSG_OPT_OS_USER_DEFINED 5

/* TODO:rtt未验证 */
#define MSG_OPT_OS MSG_OPT_OS_LINUX
// #define MSG_OPT_OS MSG_OPT_OS_freeRTOS
// #define MSG_OPT_OS MSG_OPT_OS_RT_THREAD
// #define MSG_OPT_OS MSG_OPT_OS_NONE_OR_OSAL // 裸机或osal
// #define MSG_OPT_OS MSG_OPT_OS_USER_DEFINED // 自定义

#define MSG_OPT_MUTEX_SEM // 支持互斥量和信号量

#ifdef MSG_OPT_MUTEX_SEM
enum MSG_WAIT_RET{
    WAIT_FAIL = -1, // 等待失败
    WAIT_TIMEOUT, // 等待超时
    WAIT_MSG_COME, // 需要处理消息
};
#endif

/* ----------------------- for Linux ----------------------- */
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
// #include <malloc.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include "list.h"

#ifdef MSG_OPT_MUTEX_SEM
#include <poll.h>
#include <sys/eventfd.h>
#include <unistd.h>
#define msg_mutex_t pthread_mutex_t
#define msg_mutex_lock(m) pthread_mutex_lock(m)
#define msg_mutex_unlock(m) pthread_mutex_unlock(m)
typedef struct {
    struct pollfd poll_fd;
} sync_t;
#define msg_sem_t sync_t

#else
#define msg_mutex_t 
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif

#define msg_malloc malloc
#define msg_free free
#define msg_printf printf

/* ----------------------- for freeRTOS ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include "FreeRTOS.h" 
#include "semphr.h"
#include "list.h"

#define msg_malloc pvPortMalloc
#define msg_free vPortFree
#define msg_printf printf

#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t SemaphoreHandle_t

static inline void msg_mutex_lock(msg_mutex_t *mutex) {
    if (xSemaphoreTake(*mutex, portMAX_DELAY) != pdTRUE) {
        msg_printf("lock mutex err!!\n\n");
    }
}

static inline void msg_mutex_unlock(msg_mutex_t *mutex) {
    xSemaphoreGive(*mutex);
}

#define msg_sem_t SemaphoreHandle_t

#else
#define msg_mutex_t 
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif
/* ----------------------- for RT-thread ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
#include <stdlib.h>
#include <stdio.h>
#include <rtthread.h>
#include "list.h"

#define msg_malloc rt_malloc
#define msg_free rt_free
#define msg_printf printf

#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t rt_mutex_t

static inline void msg_mutex_lock(msg_mutex_t *mutex) {
    if (rt_mutex_take(*mutex, RT_WAITING_FOREVER) != RT_EOK) {
        msg_printf("lock mutex err!!\n\n");
    }
}

static inline void msg_mutex_unlock(msg_mutex_t *mutex) {
    rt_mutex_release(*mutex);
}

#define msg_sem_t rt_sem_t

#else
#define msg_mutex_t 
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif
/* ----------------------- for none os ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_NONE_OR_OSAL)
#include <stdlib.h>
#include <stdio.h>
#include "list.h"
#undef MSG_OPT_MUTEX_SEM

#define msg_mutex_t 
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)

#define msg_malloc malloc
#define msg_free free
#define msg_printf printf

/* ----------------------- for user define ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
/* 下面示例是基于xr806移植 */
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include "list.h"

#include "../has_wifi_slab.h"
#include "../kernel/os/os.h"

#define msg_malloc test_slab_malloc
#define msg_free test_slab_free
#define msg_printf printf

#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t OS_Mutex_t

static inline void msg_mutex_lock(msg_mutex_t *mutex) {
    if (OS_MutexLock(mutex, OS_WAIT_FOREVER) != OS_OK) {
        msg_printf("lock mutex err!!\n\n");
    }
}

static inline void msg_mutex_unlock(msg_mutex_t *mutex) {
    OS_MutexUnlock(mutex);
}

#define msg_sem_t OS_Semaphore_t

#else
#define msg_mutex_t 
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif

#else
#error "!Undefined system environment!"
#endif


#endif

#ifdef MSG_OPT_MUTEX_SEM
int msg_mutex_init(msg_mutex_t *mutex);
int msg_sem_init(msg_sem_t *sem);
int msg_sem_notify(msg_sem_t *sem);
enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#endif
