/**
 * @file    app_sys.cpp
 * @brief   应用系统初始化 — X-Macro 驱动 + app_config.json 启停控制
 * @details 运行时从 <exe目录>/config/SYSTEM/app_config.json 读取模块启停配置，
 *          通过 app_modules.h X-Macro 自动生成模块列表和 g_vec_app，
 *          为每个模块创建事件 + 3 级定时器 + 独立线程。
 *
 *          配置文件目录结构:
 *            WORK_PATH/           (可执行文件所在目录)
 *            ├── RTU
 *            └── config/
 *                └── SYSTEM/
 *                    └── app_config.json
 */
#include "mySystem.h"
#include "myLog.h"
#include "myFunc.h"
#include "myDatacenter.h"
#include "cJSON.h"

#include <string>
#include <vector>
#include <set>
#include <pthread.h>


/* =========================== 消息队列 (跨模块通信) =========================== */
#define APP_MQ(name, cfg_name, msg_size, msg_num) 	{"mq_" #cfg_name, msg_size, msg_num, NULL},

stru_app_msg_queue g_app_mq[ENUM_MQ_MAX] =
{
#include "app_msg_queue.h"
};
#undef APP_MQ

static stru_mq_target g_mq_target[ENUM_MQ_MAX] =
{
	[ENUM_MQ_COM_TO_SELF_PTL] = {ENUM_APP_SELF_PTL,  EV_SELF_PTL_RX_COM},
	[ENUM_MQ_SELF_PTL_TO_COM] = {ENUM_APP_COM_ROUTER, EV_COM_RX_SELF_PTL},
};

stru_app_msg_queue *app_get_msg_queue_ptr(uint32_t mq_id)
{
	if(mq_id >= ENUM_MQ_MAX) return NULL;
	return &g_app_mq[mq_id];
}

stru_mq_target app_get_mq_target(uint32_t mq_id)
{
	if(mq_id >= ENUM_MQ_MAX) { stru_mq_target empty = {ENUM_APP_MAX, 0}; return empty; }
	return g_mq_target[mq_id];
}

static int app_mq_create(void)
{
	int i;
	for(i = 0; i < ENUM_MQ_MAX; i++)
	{
		stru_app_msg_queue *mq = &g_app_mq[i];
		mq->p_msg_queue = task_msg_queue_create(mq->name, mq->msg_size, mq->msg_num);
		if(NULL == mq->p_msg_queue) { LOG_E("app_mq_create: failed for %s", mq->name); return -1; }
	}
	LOG_I("app_mq_create: %d queues created", ENUM_MQ_MAX);
	return 0;
}

/* ---- 启用的应用名集合（从 app_config.json 读取） ---- */
static std::set<std::string> g_enabled_apps;

/* ---- 线程句柄（用于 stop 时 join） ---- */
static std::vector<pthread_t> g_threads;

/* ---- g_vec_app — 由 app_modules.h X-Macro 自动生成 ---- */
static std::vector<stru_app> g_vec_app =
{
#define APP_MODULE(name, cfg_name, init1, init2, func) \
    {"app_" #cfg_name, 0, init1, init2, (app_func_fn)func, NULL, 0, {}, {}, {}, 0},

#include "app_modules.h"
#undef APP_MODULE
};

/* ---- 三级定时器事件 ---- */
static uint32_t g_timer_event[TIMER_NUM] = {EV_TIMER1, EV_TIMER2, EV_TIMER3};

/* ---- 获取系统配置目录路径（优先级: WORK_PATH 环境变量 > 可执行文件所在目录） ---- */
static std::string get_system_config_path(void)
{
    char buf[512] = {0};

    /* 优先使用 WORK_PATH 环境变量（RK3568 装置运行时设置） */
    if (0 == func_get_work_path(buf, sizeof(buf)))
    {
        return std::string(buf) + "/config/SYSTEM/";
    }

    /* fallback: 从可执行文件路径推导（本地调试用） */
    if (0 != func_proc_self_dir(buf, sizeof(buf)))
    {
        LOG_E("func_proc_self_dir failed");

        return "";
    }

    return std::string(buf) + "/config/SYSTEM/";
}

/* ---- 解析 app_config.json ---- */
static int app_config_load(void)
{
    std::string path = get_system_config_path();

    if (path.empty())
    {
        return -1;
    }

    std::string cfg_path = path + "app_config.json";

    uint32_t fsize = 0;
    uint8_t *buf   = func_read_file_alloc(cfg_path.c_str(), &fsize);

    if (!buf)
    {
        /* 配置文件不存在时不视为错误——默认启用所有模块 */
        LOG_I("app_config.json not found, enabling all modules by default");

        for (size_t i = 0; i < g_vec_app.size(); i++)
        {
            g_enabled_apps.insert(g_vec_app[i].name);
        }

        return 0;
    }

    cJSON *root = cJSON_Parse((const char *)buf);
    free(buf);

    if (!root)
    {
        LOG_E("cJSON_Parse failed for app_config.json");

        return -1;
    }

    cJSON *apps = cJSON_GetObjectItem(root, "apps");

    if (!apps || !cJSON_IsArray(apps))
    {
        LOG_E("app_config.json missing 'apps' array");
        cJSON_Delete(root);

        return -1;
    }

    int arr_size = cJSON_GetArraySize(apps);

    for (int i = 0; i < arr_size; i++)
    {
        cJSON *item = cJSON_GetArrayItem(apps, i);

        if (!item)
        {
            continue;
        }

        cJSON *name   = cJSON_GetObjectItem(item, "name");
        cJSON *enable = cJSON_GetObjectItem(item, "enable");

        if (!name || !cJSON_IsString(name))
        {
            continue;
        }

        if (enable && cJSON_IsTrue(enable))
        {
            g_enabled_apps.insert(std::string(name->valuestring));
            LOG_I("app enabled:  %s", name->valuestring);
        }
        else
        {
            LOG_I("app disabled: %s", name->valuestring);
        }
    }

    cJSON_Delete(root);

    if (g_enabled_apps.empty())
    {
        LOG_E("no apps enabled in config");

        return -1;
    }

    return 0;
}

/* ---- 判断模块是否启用 ---- */
static bool is_app_enabled(const char *name)
{
    return g_enabled_apps.find(name) != g_enabled_apps.end();
}

/* ---- 定时器回调：发送对应的定时器事件给模块 ---- */
static void app_timer_expire(void *arg)
{
    if (!arg)
    {
        return;
    }

    uint32_t signal = *(uint32_t *)arg;
    uint8_t  thid   = signal >> 8;
    uint8_t  tm_id  = signal & 0xFF;

    if (thid >= g_vec_app.size() || tm_id >= TIMER_NUM)
    {
        return;
    }

    task_event_send(g_vec_app[thid].p_event, g_timer_event[tm_id]);
}

/* ---- 为一个模块创建 3 级定时器 ---- */
static int app_timer_create(stru_app *p_app)
{
    if (!p_app)
    {
        return -1;
    }

    uint32_t delay_ms = 1;

    for (int i = 0; i < TIMER_NUM; i++)
    {
        std::string tm_name = std::string(p_app->name) + "_tm" + std::to_string(i + 1);

        p_app->timer_arg[i] = ((p_app->app_id << 8) | i) & 0xFFFF;
        delay_ms *= 10;

        p_app->p_timer[i] = task_timer_create(
            tm_name.c_str(),
            app_timer_expire,
            (void *)&p_app->timer_arg[i],
            delay_ms,
            TASK_TIMER_FLAG_PERIODIC);

        if (!p_app->p_timer[i])
        {
            LOG_E("timer%d create failed for %s", i + 1, p_app->name);

            return -1;
        }

        task_timer_start(p_app->p_timer[i]);
    }

    return 0;
}

/* ---- 主初始化流程 ---- */
static int app_init(void)
{
    size_t i;

    /* init1: 信号注册前 */
    for (i = 0; i < g_vec_app.size(); i++)
    {
        stru_app *p = &g_vec_app[i];

        if (!p->app_init1)
        {
            continue;
        }

        if (!is_app_enabled(p->name))
        {
            LOG_I("app skipped (disabled): %s", p->name);

            continue;
        }

        if (0 != p->app_init1((void *)p))
        {
            LOG_E("app_init1 failed: %s", p->name);

            return -1;
        }
    }

    /* init2: 信号注册后 */
    for (i = 0; i < g_vec_app.size(); i++)
    {
        stru_app *p = &g_vec_app[i];

        if (!p->app_init2)
        {
            continue;
        }

        if (!is_app_enabled(p->name))
        {
            LOG_I("app skipped (disabled): %s", p->name);

            continue;
        }

        if (0 != p->app_init2((void *)p))
        {
            LOG_E("app_init2 failed: %s", p->name);

            return -1;
        }
    }

    if(0 != app_mq_create()) { LOG_E("app_mq_create"); return -1; }

    /* 创建事件 + 定时器 + 启动线程 */
    for (i = 0; i < g_vec_app.size(); i++)
    {
        stru_app *p = &g_vec_app[i];

        p->app_id = i;

        std::string ev_name = "EV_" + std::string(p->name);

        p->p_event = task_event_create(ev_name.c_str());
        if (!p->p_event)
        {
            LOG_E("task_event_create failed: %s", ev_name.c_str());

            return -1;
        }

        p->arg = (void *)p;

        if (0 != app_timer_create(p))
        {
            LOG_E("app_timer_create failed: %s", p->name);

            return -1;
        }

        if (!is_app_enabled(p->name))
        {
            LOG_I("app skipped (disabled): %s", p->name);

            continue;
        }

        pthread_t thread;

        if (0 != pthread_create(&thread, NULL, p->fun_cb, p->arg))
        {
            LOG_E("pthread_create failed: %s", p->name);

            return -1;
        }

        g_threads.push_back(thread);

        LOG_I("thread started: %s", p->name);
        task_sleep_ms(10);
    }

    return 0;
}

/* ---- 公共 API ---- */

int app_sys_init(void)
{
    if (0 != app_config_load())
    {
        LOG_E("app_config_load failed");

        return -1;
    }

    if (g_vec_app.size() != (size_t)ENUM_APP_MAX)
    {
        LOG_E("g_vec_app size mismatch: %zu vs ENUM %d",
              g_vec_app.size(), ENUM_APP_MAX);

        return -1;
    }

    if (0 != app_init())
    {
        LOG_E("app_init failed");

        return -1;
    }

    return 0;
}

/**
 * @brief  停止所有应用模块
 * @details 向每个模块发送 EV_STOP 信号，给 2 秒让线程自行退出，
 *          main 返回后 OS 回收所有资源。
 */
void app_sys_stop(void)
{
    LOG_I("stopping all app modules...");

    for (size_t i = 0; i < g_vec_app.size(); i++)
    {
        stru_app *p = &g_vec_app[i];

        if (p->p_event)
        {
            task_event_send(p->p_event, EV_STOP);
        }
    }

    task_sleep_ms(2000);

    LOG_I("app_sys_stop done");
}

stru_app *app_get_ptr(uint32_t app_id)
{
    if (app_id >= ENUM_APP_MAX)
    {
        LOG_E("app_id out of range: %u max %d", app_id, ENUM_APP_MAX);

        return NULL;
    }

    return &g_vec_app[app_id];
}
