/*
 * has_task_msg_manager/has_task_msg_manager.c
 *
 * Author: zhangzhaopeng
 * Version： 1.0
 * Created on : 2025-12-29
 * 这个软件用于代码模块之间的消息传递，采用发布-订阅的方式传递消息
 *
 */
#include <string.h>
#include "has_task_msg.h"
#include "has_task_msg_os_port.h"

// #define MSG_OPT_DYNAMIC_SUB // 允许动态订阅
// #define MSG_OPT_DEBUG // 调试

/* 暂时不支持发布列表和动态订阅同时使用，后续需要再更新支持 */
#if defined(MSG_OPT_DYNAMIC_SUB)
#error "These functions is not currently supported to be used together."
#endif

#ifdef MSG_OPT_DEBUG
#define msg_debug(fmt, ...) msg_printf("[msg]"fmt, ##__VA_ARGS__)
#else
#define msg_debug(fmt, ...)
#endif

#define MSG_ASSERT \
{msg_printf("!!!!!wrong config!!!!! file:%s line:%d\n", __FILE__, __LINE__);while(1);}

#pragma pack(1)
/* 消息数据 */
typedef struct {
    unsigned char module_id; // 发布的模块ID
    unsigned int node_cnt; // 被引用节点数
    unsigned int length;
    unsigned char buffer[];
} has_msg_buffer_t;
/* 消息节点 */
typedef struct {
    struct list_head list; // 消息链表
    has_msg_buffer_t *msg_buff;
} has_msg_node_t;
#pragma pack()

/* 静态发布列表 */
typedef struct {
    unsigned char pub_module[MODULE_MAX - 1]; // 发布表
#ifdef MSG_OPT_MUTEX_SEM
    msg_mutex_t buffer_mutex; // 消息互斥量
#endif
    unsigned char pub_num;
} has_static_pub_list_t;
static has_static_pub_list_t g_pub_list[MODULE_MAX] = {0};

/* 静态订阅列表 */
typedef struct {
#if defined(MSG_OPT_DYNAMIC_SUB)
    unsigned char module_id; // 当前模块ID
    unsigned char sub_module_cnt; // 订阅数量
    unsigned char sub_module[MODULE_MAX - 1]; // 订阅表
#else
    const unsigned char module_id; // 当前模块ID
    const unsigned char sub_module_cnt; // 订阅数量
    const unsigned char sub_module[MODULE_MAX - 1]; // 订阅表
#endif
#ifdef MSG_OPT_MUTEX_SEM
    msg_mutex_t msg_mutex; // 消息互斥量
    msg_sem_t sem;
#endif
    struct list_head msg_list; // 消息链表
} has_static_sub_list_t;
static has_static_sub_list_t g_sub_list[] = SUBSCIBE_INFO;
static unsigned char g_sub_list_index[MODULE_MAX]; // 订阅表id索引，同时表示模块是否可用


/* 检查ID是否合法，id:检查的ID，ret:不合法时return的值 */
#define MSG_CHECK_MODULE_ID(id, ret) \
if (((id) >= MODULE_MAX) || ((id) == INVALID_ID)) { \
    msg_printf("%s ID wrong:%d\n", __func__, (id)); return (ret); }

/* 检查ID和索引是否合法，id:检查的ID，ret:不合法时return的值 */
#define MSG_CHECK_ID_AND_INDEX(id, ret) \
if (((id) >= MODULE_MAX) || ((id) == INVALID_ID)) { \
    msg_printf("%s ID wrong:%d\n", __func__, (id)); return (ret); } \
if (g_sub_list_index[(id)] == MODULE_MAX) { \
    return (ret);}

/**
 * @brief 初始化消息表,必须在所有接口调用之前调用init
 *
 * @return 0:成功 -1：失败
 */
int has_msg_init()
{
    int j;
    has_static_pub_list_t *pub_list;
    /* 设置无效，标记是否初始化 */
    memset(g_sub_list_index, MODULE_MAX, sizeof(g_sub_list_index));
    memset(g_pub_list, 0, sizeof(g_pub_list));
    for (unsigned int i = 0; i < (sizeof(g_sub_list) / sizeof(g_sub_list[0])); i++) {
#ifdef CHECK_SUBSCIBE_INFO
        /* 检查各模块ID是否配置正确 */
        if ((g_sub_list[i].module_id >= MODULE_MAX) || (g_sub_list[i].module_id == INVALID_ID)) {
            msg_printf("module_id:%d is invalid, please check the macro:SUBSCIBE_INFO row:%d\n"
                , g_sub_list[i].module_id, i);
            MSG_ASSERT; // 配置都能写错，必须进断言
            return -1;
        }
        /* 已经被初始化了，配置错误 */
        if (g_sub_list_index[g_sub_list[i].module_id] != MODULE_MAX) {
            msg_printf("[msg warning]: msg two same module id:%d\n", g_sub_list[i].module_id);
            MSG_ASSERT; // 配置都能写错，必须进断言
        }

        /* 检查订阅表ID是否配置正确 */
        for (j = 0; j < (MODULE_MAX - 1); j++) {
            if (g_sub_list[i].sub_module[j] == INVALID_ID) {
                break;
            } else if (g_sub_list[i].sub_module[j] >= MODULE_MAX) {
                msg_printf("sub_module id:%d is invalid, module:id %d\n"
                    "please check the macro: SUBSCIBE_INFO row:%d, sub list:%d\n"
                    , g_sub_list[i].sub_module[j] , g_sub_list[i].module_id, i, j);
                MSG_ASSERT; // 配置都能写错，必须进断言
                return -1;
            }
        }
        /* 检查订阅数量是否配置正确 */
        if (g_sub_list[i].sub_module_cnt != j) {
            msg_printf("sub_module_cnt is config as %d, which actually is %d,"
                "please check the macro: SUBSCIBE_INFO row:%d\n"
                , g_sub_list[i].sub_module_cnt, j, i);
            MSG_ASSERT; // 配置都能写错，必须进断言
            return -1;
        }
#endif

        /* 通知发布者，需要发给此模块 */
        for (int k = 0; k < g_sub_list[i].sub_module_cnt; k++) { // 寻找发布者
            pub_list = &g_pub_list[g_sub_list[i].sub_module[k]];
#ifdef MSG_OPT_MUTEX_SEM
            if (pub_list->pub_num == 0) {
                if (msg_mutex_init(&pub_list->buffer_mutex) != 0) {
                    msg_printf("[msg warning]:pub mutex init err! pub id:%d\n"
                        , g_sub_list[i].sub_module[k]);
                    /* 使用计数没有加锁，释放msg的内存时有可能出错 */
                    continue;
                }
            }
#endif

            /* 注册所找到发布者的发布表 */
            pub_list->pub_module[pub_list->pub_num] = g_sub_list[i].module_id;
            pub_list->pub_num ++;
        }
        INIT_LIST_HEAD(&g_sub_list[i].msg_list); // 初始化订阅链表
#ifdef MSG_OPT_MUTEX_SEM
        if (msg_sem_init(&g_sub_list[i].sem) != 0) { // 初始化该模块同步量
            msg_printf("[msg warning]:sub sem init err! sub id:%d\n", i);
            continue;
        }
        if (msg_mutex_init(&g_sub_list[i].msg_mutex) != 0) { // 初始化该模块互斥量
            msg_printf("[msg warning]:sub mutex init err! sub id:%d\n", i);
            continue;
        }
#endif
        g_sub_list_index[g_sub_list[i].module_id] = i; // 索引表赋值,相当于enable
    }
#ifdef MSG_OPT_DEBUG
    // msg_printf("show index:\n");
    // for (int i = 0; i < MODULE_MAX; i++)
    // {
    //     msg_printf("sub id:%d, index:%d\n", i, g_sub_list_index[i]);
    // }
    // for (int i = 0; i < (sizeof(g_sub_list) / sizeof(g_sub_list[0])); i++) {
    //     msg_printf("module:%d subscribes to:\n", g_sub_list[i].module_id);
    //     for (int x = 0; x < g_sub_list[i].sub_module_cnt; x++) {
    //         msg_printf("%d ", g_sub_list[i].sub_module[x]);
    //     }
    //     msg_printf("\n");
    // }
    // msg_printf("\n");
    // for (int i = 1; i < MODULE_MAX; i++) {
    //     msg_printf("module:%d publish to:\n", i);
    //     for (int x = 0; x < g_pub_list[i].pub_num; x++) {
    //         msg_printf("%d ", g_pub_list[i].pub_module[x]);
    //     }
    //     msg_printf("\n");
    // }
#endif
    return 0;
}

/**
 * @brief 根据模块分别初始化消息表
 *
 * @param module_id:模块id号
 * @return 0:成功 -1：失败
 * 用于HAS OS中的初始化
 */
int has_msg_init_module(has_module_ID_e module_id)
{
    unsigned int i;
    int j;
    has_static_pub_list_t *pub_list;
    /* 检查ID */
#ifdef CHECK_SUBSCIBE_INFO
    if ((module_id >= MODULE_MAX) || (module_id == INVALID_ID)) {
        msg_printf("%s:module_id:%d is invalid\n", __func__, module_id);
        MSG_ASSERT; // 配置都能写错，必须进断言
        return -1;
    }
#endif
    /* 初始化该模块订阅表 */
    for (i = 0; i < (sizeof(g_sub_list) / sizeof(g_sub_list[0])); i++)
    {
        if (g_sub_list[i].module_id == (unsigned char)module_id) {
#ifdef CHECK_SUBSCIBE_INFO
            /* 已经被初始化了，配置错误 */
            if (g_sub_list_index[module_id] != MODULE_MAX) {
                msg_printf("[msg warning]: msg two same module id:%d\n", module_id);
                MSG_ASSERT; // 配置都能写错，必须进断言
            }
            /* 检查订阅表ID是否配置正确 */
            for (j = 0; j < (MODULE_MAX - 1); j++) {
                if (g_sub_list[i].sub_module[j] == INVALID_ID) {
                    break;
                } else if (g_sub_list[i].sub_module[j] >= MODULE_MAX) {
                    msg_printf("sub_module id:%d is invalid, module:id %d\n"
                        "please check the macro: SUBSCIBE_INFO row:%d, sub list:%d\n"
                        , g_sub_list[i].sub_module[j], module_id, i, j);
                    MSG_ASSERT; // 配置都能写错，必须进断言
                    return -1;
                }
            }

            /* 检查订阅数量是否配置正确 */
            if (g_sub_list[i].sub_module_cnt != j) {
                msg_printf("sub_module_cnt is config as %d, which actually is %d,"
                    "please check the macro: SUBSCIBE_INFO row:%d\n"
                    , g_sub_list[i].sub_module_cnt, j, i);
                MSG_ASSERT; // 配置都能写错，必须进断言
                return -1;
            }
#endif

            /* 通知发布者，需要发给此模块 */
            for (int k = 0; k < g_sub_list[i].sub_module_cnt; k++) { // 寻找发布者
                pub_list = &g_pub_list[g_sub_list[i].sub_module[k]];
#ifdef MSG_OPT_MUTEX_SEM
                if (pub_list->pub_num == 0) {
                    if (msg_mutex_init(&pub_list->buffer_mutex) != 0) {
                        msg_printf("[msg warning]:pub mutex init err! pub id:%d\n"
                            , g_sub_list[i].sub_module[k]);
                        /* 使用计数没有加锁，释放msg的内存时有可能出错 */
                        continue;
                    }
                }
#endif

                /* 注册所找到发布者的发布表 */
                pub_list->pub_module[pub_list->pub_num] = module_id;
                pub_list->pub_num ++;
            }
            INIT_LIST_HEAD(&g_sub_list[i].msg_list); // 初始化订阅链表
#ifdef MSG_OPT_MUTEX_SEM
            if (msg_sem_init(&g_sub_list[i].sem) != 0) { // 初始化该模块同步量
                msg_printf("[msg warning]:sub sem init err! sub id:%d\n", i);
                break;
            }
            if (msg_mutex_init(&g_sub_list[i].msg_mutex) != 0) { // 初始化该模块互斥量
                msg_printf("[msg warning]:sub mutex init err! sub id:%d\n", i);
                break;
            }
#endif
            g_sub_list_index[module_id] = i; // 索引表赋值,相当于enable
            break;
        }
    }

#ifdef MSG_OPT_DEBUG
    if (i == (sizeof(g_sub_list) / sizeof(g_sub_list[0]))) {
        msg_debug("module:%d never subscribe any module\n", module_id);
    }
#endif
    return 0;
}

/* 如果是OS初始化，则用下列类似调用方式，先清除
需要初始化的模块再调用 has_msg_init_module 传相应ID */
int has_msg_os_init()
{
    /* 设置无效，标记是否初始化 */
    memset(g_sub_list_index, MODULE_MAX, sizeof(g_sub_list_index));
    memset(g_pub_list, 0, sizeof(g_pub_list));
    for (int i = INVALID_ID + 1; i < MODULE_MAX; i++)
    {
        has_msg_init_module(i);
    }
    return 0;
}

/* TODO:更合理的方式是每个消息一个互斥量，但是可能会导致每个消息malloc和free的时候频繁init和deinit */

/* 检查计数判断该消息是否被所有订阅模块处理完，处理完就释放内存 */
static inline void msg_check_and_free_message(has_msg_node_t *node)
{
    has_msg_node_t *temp = NULL;
    unsigned char id = node->msg_buff->module_id;
#ifdef MSG_OPT_MUTEX_SEM
    msg_mutex_t *target_mutex = &g_pub_list[id].buffer_mutex;
#endif
    msg_mutex_lock(target_mutex);
    node->msg_buff->node_cnt --;
    if (node->msg_buff->node_cnt == 0) {
        temp = ((has_msg_node_t *)node->msg_buff - g_pub_list[id].pub_num);
    }
    msg_mutex_unlock(target_mutex);
    if (temp) {
        msg_debug("free node addr:%p\n", temp);
        msg_free(temp);
    }
}

/**
 * @brief 发布一个消息
 *
 * @param module_id:发布消息的模块id号
 * @param buffer:消息数据指针
 * @param length:消息数据长度
 * @return 0:成功 -1：失败
 */
int has_msg_publish(has_module_ID_e module_id, void *buffer, unsigned int length)
{
    has_msg_node_t *node;
    if (buffer == NULL) {
        return -1;
    }
    // if (length == 0) {
    //     return -1;
    // }
    has_msg_buffer_t *msg_buffer;
    has_static_pub_list_t *pub_list;
    has_static_sub_list_t *sub_list;

    MSG_CHECK_ID_AND_INDEX(module_id, -1);
    // MSG_CHECK_MODULE_ID 如果使用这个宏检查，未初始化的模块也可以发布
    pub_list = &g_pub_list[module_id];
    if (pub_list->pub_num == 0) {
        // msg_printf("no one subscribe you:%d\n", module_id);
        return 0;
    }

    /* 根据订阅表分配内存 */
    node = (has_msg_node_t *)msg_malloc((sizeof(has_msg_node_t) * pub_list->pub_num)
    + sizeof(has_msg_buffer_t) + length);
    if (node == NULL) {
        msg_printf("malloc fail,pub id:%d\n", module_id);
        return -1;
    }
    msg_debug("publish: id:%d node addr:%p\n", module_id, node);
    msg_buffer = (has_msg_buffer_t *)(&node[pub_list->pub_num]);
    msg_buffer->node_cnt = pub_list->pub_num;
    msg_buffer->length = length;
    msg_buffer->module_id = module_id;
    memcpy(msg_buffer->buffer, buffer, length);
    /* 查订阅表添加消息 */
    for (int i = 0; i < pub_list->pub_num; i++) {
        sub_list = &g_sub_list[g_sub_list_index[pub_list->pub_module[i]]];
        node[i].msg_buff = msg_buffer;
        msg_mutex_lock(&sub_list->msg_mutex);
        list_add_tail(&node[i].list, &sub_list->msg_list); // 加入消息链表
#ifdef MSG_OPT_MUTEX_SEM
        /* 通知等待线程唤醒 */
        if (msg_sem_notify(&sub_list->sem) == -1) {
            list_del(&node[i].list); // 添加失败，删除链表
            msg_mutex_unlock(&sub_list->msg_mutex);
            msg_check_and_free_message(&node[i]);
            msg_printf("[msg warning]:Failed to add msg on module:%d !!!\n"
                , sub_list->module_id);
            continue;
        }
#endif
        msg_mutex_unlock(&sub_list->msg_mutex);
    }
    return 0;
}

/**
 * @brief 处理一个消息,先入先出
 *
 * @param module_id:处理消息的模块id号
 * @param cb:消息处理回调
 * @param ms_timeout:超时时间（ms）其中0：消息直接返回；-1：一直阻塞
 * @return 0:成功 -1：失败
 */
int has_msg_handle(has_module_ID_e module_id, has_msg_handle_cb cb, int ms_timeout)
{
    has_msg_node_t *node;
    has_static_sub_list_t *sub_list;
    MSG_CHECK_ID_AND_INDEX(module_id, -1);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

#ifdef MSG_OPT_MUTEX_SEM
    if (msg_sem_wait(&sub_list->sem, ms_timeout) != WAIT_MSG_COME) {
        return -1; // 没有消息需要处理或发生错误
    }
#endif

    /* 处理一个消息，先入先出 */
    msg_mutex_lock(&sub_list->msg_mutex);
    if (!list_empty(&sub_list->msg_list)) {
        node = list_first_entry(&sub_list->msg_list, has_msg_node_t, list);
        list_del(&node->list);
        msg_mutex_unlock(&sub_list->msg_mutex);
    } else { // 没有消息需要处理
        msg_mutex_unlock(&sub_list->msg_mutex);
        return -1;
    }

    if (cb != NULL) {
        cb(node->msg_buff->module_id, node->msg_buff->buffer, node->msg_buff->length);
    }
    msg_debug("handle:pub id:%d handle id:%d\n", node->msg_buff->module_id, module_id);
    msg_check_and_free_message(node);


    return 0;
}

/**
 * @brief 处理一个指定发布者的消息,先入先出
 *
 * @param module_id:处理消息的模块id号
 * @param cb:消息处理回调
 * @param pub_module_id:指定发布者的id号
 * @return 0:成功 -1：失败
 */
int has_msg_handle_by_module(has_module_ID_e module_id, has_msg_handle_cb cb,
    has_module_ID_e pub_module_id)
{
    has_msg_node_t *node, *temp;
    has_static_sub_list_t *sub_list;
    MSG_CHECK_ID_AND_INDEX(module_id, -1);
    MSG_CHECK_MODULE_ID(pub_module_id, -1);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

    /* 处理一个指定模块的消息，先入先出 */
    msg_mutex_lock(&sub_list->msg_mutex);
    if (!list_empty(&sub_list->msg_list)) {
        list_for_each_entry_safe(node, temp, &sub_list->msg_list, list) {
            if (node->msg_buff->module_id == (unsigned char)pub_module_id) {
#ifdef MSG_OPT_MUTEX_SEM
                if (msg_sem_wait(&sub_list->sem, 0) != WAIT_MSG_COME) {
                    msg_mutex_unlock(&sub_list->msg_mutex);
                    msg_printf("error: list number != sem number\n");
                    return -1; // eventfd和list不一致，理论上一定是 WAIT_MSG_COME
                }
#endif
                list_del(&node->list);
                msg_mutex_unlock(&sub_list->msg_mutex);
                if (cb != NULL) {
                    cb(node->msg_buff->module_id, node->msg_buff->buffer, node->msg_buff->length);
                }
                msg_debug("by handle:pub id:%d handle id:%d\n", node->msg_buff->module_id, module_id);
                msg_check_and_free_message(node);
                return 0;
            }
        }
    }
    // 没有消息需要处理
    msg_mutex_unlock(&sub_list->msg_mutex);
    return -1;
}

/**
 * @brief 处理一个最近收到的消息
 *
 * @param module_id:处理消息的模块id号
 * @param cb:消息处理回调
 * @return 0:成功 -1：失败
 */
int has_msg_handle_latest(has_module_ID_e module_id, has_msg_handle_cb cb, int ms_timeout)
{
    has_msg_node_t *node;
    has_static_sub_list_t *sub_list;
    MSG_CHECK_ID_AND_INDEX(module_id, -1);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

#ifdef MSG_OPT_MUTEX_SEM
    if (msg_sem_wait(&sub_list->sem, ms_timeout) != WAIT_MSG_COME) {
        return -1; // 没有消息需要处理或发生错误
    }
#endif

    /* 处理最新的消息 */
    msg_mutex_lock(&sub_list->msg_mutex);
    if (!list_empty(&sub_list->msg_list)) {
        node = list_last_entry(&sub_list->msg_list, has_msg_node_t, list);
        list_del(&node->list);
        msg_mutex_unlock(&sub_list->msg_mutex);
    } else { // 没有消息需要处理
        msg_mutex_unlock(&sub_list->msg_mutex);
        return -1;
    }

    if (cb != NULL) {
        cb(node->msg_buff->module_id, node->msg_buff->buffer, node->msg_buff->length);
    }
    msg_debug("handle:pub id:%d handle id:%d\n", node->msg_buff->module_id, module_id);
    msg_check_and_free_message(node);


    return 0;
}

/* 将消息复制出接口处理，不建议使用 */
#if 1
unsigned int has_msg_receive(has_module_ID_e module_id, unsigned char *pub_module_id,
    unsigned char *buf_out, int ms_timeout)
{
    has_msg_node_t *node;
    has_static_sub_list_t *sub_list;
    unsigned int len = 0;
    if (buf_out == NULL) {
        msg_printf("%s buff is NULL\n", __func__);
        return 0;
    }
    MSG_CHECK_ID_AND_INDEX(module_id, 0);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

#ifdef MSG_OPT_MUTEX_SEM
    if (msg_sem_wait(&sub_list->sem, ms_timeout) != WAIT_MSG_COME) {
        return 0; // 没有消息需要处理或发生错误
    }
#endif

    /* 处理一个消息，先入先出 */
    msg_mutex_lock(&sub_list->msg_mutex);
    if (!list_empty(&sub_list->msg_list)) {
        node = list_first_entry(&sub_list->msg_list, has_msg_node_t, list);
        list_del(&node->list);
        msg_mutex_unlock(&sub_list->msg_mutex);
    } else { // 没有消息需要处理
        msg_mutex_unlock(&sub_list->msg_mutex);
        return 0;
    }

    memcpy(buf_out, node->msg_buff->buffer, node->msg_buff->length);
    if (pub_module_id != NULL) {
        *pub_module_id = node->msg_buff->module_id;
    }
    len = node->msg_buff->length;
    msg_debug("handle:pub id:%d handle id:%d\n", node->msg_buff->module_id, module_id);
    msg_check_and_free_message(node);
    return len;
}

unsigned int has_msg_receive_latest(has_module_ID_e module_id, unsigned char *pub_module_id,
    unsigned char *buf_out, int ms_timeout)
{
    has_msg_node_t *node;
    has_static_sub_list_t *sub_list;
    unsigned int len = 0;
    if (buf_out == NULL) {
        msg_printf("%s buff is NULL\n", __func__);
        return 0;
    }
    MSG_CHECK_ID_AND_INDEX(module_id, 0);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

#ifdef MSG_OPT_MUTEX_SEM
    if (msg_sem_wait(&sub_list->sem, ms_timeout) != WAIT_MSG_COME) {
        return 0; // 没有消息需要处理或发生错误
    }
#endif

    /* 处理最新的消息 */
    msg_mutex_lock(&sub_list->msg_mutex);
    if (!list_empty(&sub_list->msg_list)) {
        node = list_last_entry(&sub_list->msg_list, has_msg_node_t, list);
        list_del(&node->list);
        msg_mutex_unlock(&sub_list->msg_mutex);
    } else { // 没有消息需要处理
        msg_mutex_unlock(&sub_list->msg_mutex);
        return 0;
    }

    memcpy(buf_out, node->msg_buff->buffer, node->msg_buff->length);
    if (pub_module_id != NULL) {
        *pub_module_id = node->msg_buff->module_id;
    }
    len = node->msg_buff->length;
    msg_debug("handle:pub id:%d handle id:%d\n", node->msg_buff->module_id, module_id);
    msg_check_and_free_message(node);
    return len;
}
#endif

/**
 * @brief 判断消息链表是否是空，没有消息要处理就是空
 *
 * @param module_id:要查空的模块id号
 * @return 0:没有消息 -1：有消息待处理
 */
unsigned int has_msg_is_message_empty(has_module_ID_e module_id)
{
    has_static_sub_list_t *sub_list;
    MSG_CHECK_ID_AND_INDEX(module_id, -1);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

    msg_mutex_lock(&sub_list->msg_mutex);
    if (list_empty(&sub_list->msg_list)) {
        msg_mutex_unlock(&sub_list->msg_mutex);
        return 0;
    } else {
        msg_mutex_unlock(&sub_list->msg_mutex);
        return -1;
    }
}

/**
 * @brief 获取待处理消息的个数
 *
 * @param module_id:处理消息的模块id号
 * @return num : 消息数量
 */
unsigned int has_msg_get_message_number(has_module_ID_e module_id)
{
    has_msg_node_t *node, *temp;
    has_static_sub_list_t *sub_list;
    unsigned int num = 0;
    MSG_CHECK_ID_AND_INDEX(module_id, 0);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

    msg_mutex_lock(&sub_list->msg_mutex);
    list_for_each_entry_safe(node, temp, &sub_list->msg_list, list) {
        num ++;
    }
    msg_mutex_unlock(&sub_list->msg_mutex);
    return num;
}

int has_msg_printf_subscribe(has_module_ID_e module_id)
{
    has_static_sub_list_t *sub_list;
    MSG_CHECK_ID_AND_INDEX(module_id, -1);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

    msg_printf("module:%d subscribes to:\n", module_id);
    for (int i = 0; i < sub_list->sub_module_cnt; i++) {
        msg_printf("%d ", sub_list->sub_module[i]);
    }
    msg_printf("\n");
    return 0;
}

/**
 * @brief 删除所有未处理的消息
 *
 * @param module_id:处理消息的模块id号
 * @return 0:成功 -1：失败
 */
int has_msg_delete_all_message(has_module_ID_e module_id)
{
    has_msg_node_t *node, *temp;
    has_static_sub_list_t *sub_list;
    struct list_head free_list;
    INIT_LIST_HEAD(&free_list);
    int ret = 0;
    MSG_CHECK_ID_AND_INDEX(module_id, -1);

    sub_list = &g_sub_list[g_sub_list_index[module_id]];

    msg_mutex_lock(&sub_list->msg_mutex);
    if (!list_empty(&sub_list->msg_list)) {
        list_for_each_entry_safe(node, temp, &sub_list->msg_list, list) {
#ifdef MSG_OPT_MUTEX_SEM
            if (msg_sem_wait(&sub_list->sem, 0) != WAIT_MSG_COME) {
                msg_printf("error: list number != sem number\n");
                ret = -1;
                continue; // eventfd和list不一致，理论上一定是 WAIT_MSG_COME
            }
#endif
            list_del(&node->list);
            list_add_tail(&node->list, &free_list); // 加入临时链表
        }
    }
    // INIT_LIST_HEAD(&sub_list->msg_list);
    msg_mutex_unlock(&sub_list->msg_mutex);
    /* 释放内存 */
	list_for_each_entry_safe(node, temp, &free_list, list) {
        msg_check_and_free_message(node);
	}
    return ret;
}

#ifdef MSG_OPT_DYNAMIC_SUB
int has_msg_subscribe(has_module_ID_e module_id, has_module_ID_e sub_id)
{
    has_static_sub_list_t *sub_list;
    int j;
    if ((sub_id >= MODULE_MAX) || (sub_id == INVALID_ID)) {
        return -1;
    }
    MSG_CHECK_ID_AND_INDEX(module_id, -1);
    sub_list = &g_sub_list[g_sub_list_index[module_id]];

    msg_mutex_lock(&sub_list->msg_mutex);
    if (sub_list->sub_module_cnt < (MODULE_MAX - 1)) {
        /* 检查是否已经订阅 */
        for (j = 0; j < sub_list->sub_module_cnt; j++) {
            if ((unsigned char)sub_id == sub_list->sub_module[j]) {
                msg_mutex_unlock(&sub_list->msg_mutex);
                msg_printf("ID:%d has been sub by module:%d\n", sub_id, module_id);
                return -1;
            }
        }
        /* 加入该模块的订阅表中 */
        sub_list->sub_module[j] = sub_id;
        sub_list->sub_module_cnt ++;
        msg_mutex_unlock(&sub_list->msg_mutex);
        return 0;
    }
    else {
        msg_mutex_unlock(&sub_list->msg_mutex);
        msg_printf("module:%d subscribe fail\n", module_id);
        return -1;
    }
}

int has_msg_unsubscribe(has_module_ID_e module_id, has_module_ID_e sub_id)
{
    has_static_sub_list_t *sub_list;
    if ((sub_id >= MODULE_MAX) || (sub_id == INVALID_ID)) {
        return -1;
    }
    MSG_CHECK_ID_AND_INDEX(module_id, -1);
    sub_list = &g_sub_list[g_sub_list_index[module_id]];

    msg_mutex_lock(&sub_list->msg_mutex);
    for (int j = 0; j < sub_list->sub_module_cnt; j++) {
        if ((unsigned char)sub_id == sub_list->sub_module[j]) {
            sub_list->sub_module[j] = INVALID_ID;
            sub_list->sub_module_cnt --;
        }
    }
    msg_mutex_unlock(&sub_list->msg_mutex);
    return 0;
}
#endif
