/** @file dc_core.cpp — 全局变量 + 哈希操作 + 生命周期 */
#include "dc_internal.h"

dc_signal_map_t g_dc_out = {};
dc_signal_map_t g_dc_yk = {};
dc_signal_map_t g_dc_ao = {};
dc_signal_map_t g_dc_param = {};

std::vector<dc_signal_t *> g_dirty_out_signals;
std::mutex g_dirty_out_mutex;

dc_async_queue_t g_async_queue = {};

bool g_param_cfg_changed = false;
std::mutex g_param_cfg_mutex;

char g_cfg_dir[256] = {0};
bool g_initialized = false;

std::unordered_map<std::string, dc_param_meta_t> g_param_metadata;

/** @brief 添加脏信号到列表，由 100ms 周期检测变更 */
void dc_core_mark_dirty(dc_signal_t *p_signal)
{
    if (!p_signal)
    {
        return;
    }

    std::lock_guard<std::mutex> lk(g_dirty_out_mutex);
    g_dirty_out_signals.push_back(p_signal);
}

/** @brief 计算 saddr 的 XXH128 哈希 */
static XXH128_hash_t dc_core_hash(const char *saddr)
{
    return XXH3_128bits(saddr, strlen(saddr));
}

/** @brief 添加信号到 map（已存在则更新） */
int dc_core_add(dc_signal_t &signal, dc_signal_map_t &smap)
{
    std::lock_guard<std::mutex> lk(smap.mtx);
    auto range = smap.map_signals.equal_range(signal.hash);

    for (auto it = range.first; it != range.second; ++it)
    {
        if (0 == strcmp(it->second.saddr, signal.saddr))
        {
            uint32_t oid = it->second.id;

            it->second = signal;
            it->second.id = oid;

            return DC_OK;
        }
    }

    auto it = smap.map_signals.emplace(signal.hash, signal);

    it->second.id = smap.signal_id++;

    if (smap.id_index.size() <= it->second.id)
    {
        smap.id_index.resize(it->second.id + 1, NULL);
    }

    smap.id_index[it->second.id] = &it->second;

    return DC_OK;
}

/** @brief 按 saddr 在指定 map 中查找信号 */
dc_signal_t *dc_core_find(const char *saddr, dc_signal_map_t &smap)
{
    if (!saddr)
    {
        return NULL;
    }

    XXH128_hash_t h = dc_core_hash(saddr);
    std::lock_guard<std::mutex> lk(smap.mtx);
    auto range = smap.map_signals.equal_range(h);

    for (auto it = range.first; it != range.second; ++it)
    {
        if (0 == strcmp(it->second.saddr, saddr))
        {
            return &it->second;
        }
    }

    return NULL;
}

/** @brief 快捷查找 out 信号 */
dc_signal_t *dc_core_find_out(const char *saddr)
{
    return dc_core_find(saddr, g_dc_out);
}

/** @brief 按 ID 查找信号（O(1)） */
dc_signal_t *dc_core_find_by_id(uint32_t id, dc_signal_map_t &smap)
{
    std::lock_guard<std::mutex> lk(smap.mtx);

    if (id >= smap.id_index.size())
    {
        return NULL;
    }

    return smap.id_index[id];
}

/* ========== 生命周期 ========== */

/** @brief 初始化 datacenter，设置全局变量并尝试加载 param.xml */
int dc_init(const char *cfg_dir)
{
    if (g_initialized)
    {
        LOG_I("datacenter already init\n");

        return DC_OK;
    }

    if (cfg_dir)
    {
        strncpy(g_cfg_dir, cfg_dir, sizeof(g_cfg_dir) - 1);
    }

    g_async_queue.max_pending = DC_MAX_PENDING;
    g_async_queue.default_timeout_ms = 30000;

    g_initialized = true;

    /* 尝试加载参数配置文件 */
    if (cfg_dir && cfg_dir[0])
    {
        char param_path[512];

        snprintf(param_path, sizeof(param_path), "%s/param.xml", cfg_dir);
        if (0 != dc_param_cfg_parse(param_path))
        {
            LOG_I("no param.xml at %s, skipping config load\n", param_path);
        }
    }

    LOG_I("datacenter init ok, cfg=%s\n", g_cfg_dir);

    return DC_OK;
}

/** @brief 清理 datacenter */
void dc_cleanup(void)
{
    if (!g_initialized)
    {
        return;
    }

    g_dirty_out_signals.clear();
    g_initialized = false;
    LOG_I("datacenter cleaned up\n");
}

/** @brief 100ms 变化检测：去重 → 值比对 → 回调 → 回路阻断 */
static void dc_change_out_check(void)
{
    std::vector<dc_signal_t *> dirty;

    {
        std::lock_guard<std::mutex> lk(g_dirty_out_mutex);
        dirty.swap(g_dirty_out_signals);
    }

    if (dirty.empty())
    {
        return;
    }

    std::sort(dirty.begin(), dirty.end());
    auto last = std::unique(dirty.begin(), dirty.end());

    for (auto it = dirty.begin(); it != last; ++it)
    {
        dc_signal_t *ps = *it;

        if (!ps->vec_p_data || !ps->vec_p_data[0] || !ps->p_last_data)
        {
            continue;
        }

        if (0 == dc_util_val_compare(ps->data_type, ps->vec_p_data[0], ps->p_last_data))
        {
            continue;
        }

        for (int i = 0; i < ps->cb_count; i++)
        {
            if (!ps->cb_list[i].out_cb)
            {
                continue;
            }

            /* 回路阻断: 仅当单模块写入且回调属于该模块时跳过 */
            if (!ps->dirty_by_multi && 0 == strcmp(ps->cb_list[i].module_id, ps->last_caller_module))
            {
                continue;
            }

            ps->cb_list[i].out_cb(ps->saddr, ps->data_type, ps->vec_p_data[0], ps->p_last_data);
        }

        dc_util_val_copy(ps->p_last_data, ps->vec_p_data[0], ps->data_type);
        ps->dirty_by_multi = 0;
        ps->last_caller_module[0] = '\0';
    }
}

/** @brief 100ms 周期：变化检测 + 事件出队 + 异步超时检查 */
void dc_run_100ms(void)
{
    dc_change_out_check();
    dc_disturb_dd_queue_pop();
    dc_event_queue_pop();
    dc_fault_queue_pop();
    dc_async_timeout_check();
    dc_async_cleanup();
}

/** @brief 1000ms 周期：参数配置文件变更检测 */
void dc_run_1000ms(void)
{
    dc_param_cfg_check(g_cfg_dir);
}

