/** @file dc_signal_out.cpp — Out 信号注册/链接/设值 */
#include "dc_internal.h"

/** @brief Out 信号注册内部实现：创建信号、分配内存、注册回调 */
static int dc_out_register_impl(const char *saddr, const char *desc, uint8_t data_type, void *p_data, dc_out_change_cb_t cb, const char *module_id)
{
    if (!g_initialized || !saddr || !p_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    if (dc_core_find_out(saddr))
    {
        LOG_E("out %s exists\n", saddr);

        return DC_ERR_EXISTS;
    }

    dc_signal_t sig = {};

    sig.hash = XXH3_128bits(saddr, strlen(saddr));
    strncpy(sig.saddr, saddr, DC_SADDR_MAX_LEN - 1);

    if (desc)
    {
        strncpy(sig.desc, desc, DC_DESC_MAX_LEN - 1);
    }

    sig.data_type = data_type;
    sig.vec_p_data = (void **)malloc(sizeof(void *));
    sig.vec_p_data[0] = p_data;
    sig.vec_p_data_count = 1;

    sig.p_last_data = dc_util_create_data(data_type);

    if (!sig.p_last_data)
    {
        free(sig.vec_p_data);

        return DC_ERR_MEM;
    }

    dc_util_val_copy(sig.p_last_data, p_data, data_type);

    if (cb)
    {
        strncpy(sig.cb_list[0].module_id, module_id, DC_MODULE_MAX_LEN - 1);
        sig.cb_list[0].out_cb = cb;
        sig.cb_count = 1;
    }

    return dc_core_add(sig, g_dc_out);
}

/** @brief 注册 out 信号（无回调） */
int dc_signal_out(const char *saddr, const char *desc, uint8_t data_type, void *p_data, const char *module_id)
{
    return dc_out_register_impl(saddr, desc, data_type, p_data, NULL, module_id);
}

/** @brief 注册 out 信号（带变更回调） */
int dc_signal_out_with_callback(const char *saddr, const char *desc, uint8_t data_type, void *p_data, dc_out_change_cb_t cb, const char *module_id)
{
    return dc_out_register_impl(saddr, desc, data_type, p_data, cb, module_id);
}

/** @brief 链接已有 out 信号并追加回调 */
int dc_signal_out_link_with_callback(const char *saddr, void **p_data, dc_out_change_cb_t cb, const char *module_id)
{
    if (!g_initialized || !saddr || !p_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    dc_signal_t *ps = dc_core_find_out(saddr);

    if (!ps)
    {
        return DC_ERR_NOTFOUND;
    }

    if (!ps->vec_p_data || !ps->vec_p_data[0])
    {
        return DC_ERR_PARAM;
    }

    *p_data = ps->vec_p_data[0];

    if (cb && ps->cb_count < DC_MAX_CALLBACKS)
    {
        strncpy(ps->cb_list[ps->cb_count].module_id, module_id, DC_MODULE_MAX_LEN - 1);
        ps->cb_list[ps->cb_count].out_cb = cb;
        ps->cb_count++;
    }

    return DC_OK;
}

/** @brief 设置 out 信号值（标记脏 + 回路阻断） */
int dc_set_out_signal_val(const char *saddr, const void *set_data, const char *module_id)
{
    if (!g_initialized || !saddr || !set_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    dc_signal_t *ps = dc_core_find_out(saddr);

    if (!ps)
    {
        return DC_ERR_NOTFOUND;
    }

	/* 记录调用方: 多模块同时修改时设 dirty_by_multi=1, 回路阻断时跳过所有 */
	if ('\0' == ps->last_caller_module[0])
	{
		strncpy(ps->last_caller_module, module_id, DC_MODULE_MAX_LEN - 1);
	}
	else if (0 != strcmp(ps->last_caller_module, module_id))
	{
		ps->dirty_by_multi = 1;
	}

    dc_core_mark_dirty(ps);
    dc_util_val_copy(ps->vec_p_data[0], set_data, ps->data_type);

    return DC_OK;
}

