/** @file dc_signal_in.cpp — In 信号注册 */
#include "dc_internal.h"

/** @brief In 信号注册内部实现：关联 out 信号、建立链接、追加回调 */
static int dc_in_register_impl(const char *saddr, const char *desc, const char *link_saddr, void **p_data, dc_out_change_cb_t cb, const char *module_id)
{
    if (!g_initialized || !saddr || !link_saddr || !p_data || !module_id)
    {
        return DC_ERR_PARAM;
    }

    if (!link_saddr[0])
    {
        return DC_ERR_PARAM;
    }

    if (dc_core_find_in(saddr))
    {
        LOG_E("in %s exists\n", saddr);

        return DC_ERR_EXISTS;
    }

    dc_signal_t *ps_out = dc_core_find_out(link_saddr);

    if (!ps_out)
    {
        LOG_E("link out %s not found\n", link_saddr);

        return DC_ERR_NOTFOUND;
    }

    *p_data = ps_out->vec_p_data[0];

    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 = ps_out->data_type;
    strncpy(sig.link_saddr, link_saddr, DC_SADDR_MAX_LEN - 1);
    sig.vec_p_data = (void **)malloc(sizeof(void *));
    sig.vec_p_data[0] = *p_data;
    sig.vec_p_data_count = 1;

    /* out 记录 in 的链接 */
    char **nl = (char **)realloc(ps_out->link_saddrs, (ps_out->link_count + 1) * sizeof(char *));

    nl[ps_out->link_count] = strdup(saddr);
    ps_out->link_saddrs = nl;
    ps_out->link_count++;

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

    return dc_core_add(sig, g_dc_in);
}

/** @brief 注册 in 信号（链接到 out，无回调） */
int dc_signal_in(const char *saddr, const char *desc, const char *link_saddr, void **p_data, const char *module_id)
{
    return dc_in_register_impl(saddr, desc, link_saddr, p_data, NULL, module_id);
}

/** @brief 注册 in 信号（链接到 out，带变更回调） */
int dc_signal_in_with_callback(const char *saddr, const char *desc, const char *link_saddr, void **p_data, dc_out_change_cb_t cb, const char *module_id)
{
    return dc_in_register_impl(saddr, desc, link_saddr, p_data, cb, module_id);
}

