#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和freertos未测过 */
#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>

#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_init(m) pthread_mutex_init(m, NULL)
#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

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);
#else
#define msg_mutex_t 
#define msg_mutex_init(m)
#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 "FreeRTOS.h" 
#include "semphr.h"
#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t SemaphoreHandle_t
static inline void msg_mutex_init(void *mutex) {
	*mutex = xSemaphoreCreateMutex();
    if (*mutex == NULL) {
        printf("create mutex err!!\n\n");
    }
}

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

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

#define msg_sem_t int

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);

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

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

/* ----------------------- for RT-thread ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
#include <stdlib.h>
#include <stdio.h>
#include <rtthread.h>
#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t rt_mutex_t
static inline void msg_mutex_init(void *mutex) {
	*mutex = rt_mutex_create("has_msg", RT_IPC_FLAG_FIFO);
    if (*mutex == RT_NULL) {
        printf("create mutex err!!\n\n");
    }
}

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

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

#define msg_sem_t int

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);

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

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

/* ----------------------- for none os ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_NONE_OR_OSAL)
#include <stdlib.h>
#include <stdio.h>
#undef MSG_OPT_MUTEX_SEM

#define msg_mutex_t 
#define msg_mutex_init(m)
#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)
#include <stdlib.h>
#include <stdio.h>

#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t int/* to be done */
static inline void msg_mutex_init(void *mutex) {
	/* to be done */
}

static inline void msg_mutex_lock(void *mutex) {
    /* to be done */
}

static inline void msg_mutex_unlock(void *mutex) {
    /* to be done */
}

#define msg_sem_t int // to be done

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);

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


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

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


#endif