#include <stdio.h>
#include <sys/resource.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/timerfd.h>
#include <errno.h>
#include <syslog.h>
#include <string.h>

#include "dy_common.h"
#include "cJSON.h"

/**
*******************************************************************************
*
* @brief 读取node cfg配置
* @param p_nodes_cfg 用于存储node cfg的结构
* @param cfg_file nodes cfg的配置文件
* @return 0 for success, -1 for error
*
*******************************************************************************
*/
int load_nodes_cfg(nodes_cfg_table_t **p_nodes_cfg, const char *cfg_file)
{
    char *data = NULL;
    cJSON *root = NULL;
    cJSON *nodes = NULL;
    cJSON *node = NULL;
    nodes_cfg_table_t *nodes_cfg = NULL;
    int node_cnt = 0;
    int i = 0, ret = 0, m;
    char buff[200];
    int addr[8];
    int size = 0;

    if (p_nodes_cfg == NULL || cfg_file == NULL)
    {
        dy_syslog(LOG_ERR, "p_nodes_cfg:%p cfg_file:%p", p_nodes_cfg, cfg_file);
        return -1;
    }

    data = read_file_data(cfg_file);
    if (data == NULL)
    {
        dy_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        ret = -1;
        goto out;
    }

    {
        char *new = download_url_data(data, NODES_CFG_PATH);
        if (new != NULL)
        {
            free(data);
            data = new;
        }
    }

    root = cJSON_Parse(data);
    if (!root)
    {
        dy_syslog(LOG_ERR, "parse cfg file %s error", cfg_file);
        ret = -1;
        goto out;
    }
    nodes = cJSON_GetObjectItem(root, "nodes_cfg");
    if (!nodes)
    {
        dy_syslog(LOG_ERR, "get nodes_cfg failed");
        ret = -1;
        goto out;
    }

    node_cnt = cJSON_GetArraySize(nodes);
    size = sizeof(nodes_cfg_table_t) + node_cnt * sizeof(node_cfg_t);
    nodes_cfg = calloc(1, size);
    if (nodes_cfg == NULL)
    {
        dy_syslog(LOG_ERR, "malloc failed, node_cnt:%d size:%d", node_cnt, size);
        ret = -1;
        goto out;
    }

    for (i = 0; i < node_cnt; i++)
    {
        node = cJSON_GetArrayItem(nodes, i);
        if (node)
        {
            GET_JSON_VALUE_STRING(node, "template_id", nodes_cfg->node[i].template_id);
            GET_JSON_VALUE_STRING(node, "product_key", nodes_cfg->node[i].product_key);
            GET_JSON_VALUE_STRING(node, "device_name", nodes_cfg->node[i].device_name);
            GET_JSON_VALUE_STRING(node, "device_secret", nodes_cfg->node[i].device_secret);
            GET_JSON_VALUE_STRING(node, "device_id", nodes_cfg->node[i].device_id);
            GET_JSON_VALUE_STRING(node, "huawei_app_id", nodes_cfg->node[i].huawei_app_id);
            GET_JSON_VALUE_STRING(node, "connection_string", nodes_cfg->node[i].connection_string);
            GET_JSON_VALUE_STRING(node, "sub_template_id", nodes_cfg->node[i].sub_template_id);
            cJSON *platform_name = cJSON_GetObjectItem(node, "platform_name");
            if (platform_name && cJSON_GetArraySize(platform_name))
            {
                nodes_cfg->node[i].other_platform = 1;
            }
            GET_JSON_VALUE_INT(node, "depth", nodes_cfg->node[i].depth);
            GET_JSON_VALUE_STRING(node, "sn", nodes_cfg->node[i].sn);
            GET_JSON_VALUE_STRING(node, "dtu_sn", nodes_cfg->node[i].dtu_sn);
            GET_JSON_VALUE_STRING(node, "app_key", nodes_cfg->node[i].app_key);
            GET_JSON_VALUE_DY_STRING(node, "ext_data", nodes_cfg->node[i].ext_data);
            GET_JSON_VALUE_DY_STRING(node, "user_defined", nodes_cfg->node[i].user_defined);
            GET_JSON_VALUE_STRING(node, "connect_port", buff);
            nodes_cfg->node[i].port = port_char2enum(buff);
            GET_JSON_VALUE_STRING(node, "device_type", buff);
            nodes_cfg->node[i].device_type = device_type_char2enum(buff);
            GET_JSON_VALUE_STRING(node, "appeui", nodes_cfg->node[i].appeui);
            GET_JSON_VALUE_STRING(node, "appkey", nodes_cfg->node[i].appkey);
            nodes_cfg->node[i].node_type = -1; //classA define 0
            GET_JSON_VALUE_INT(node, "node_type", nodes_cfg->node[i].node_type);
            if (nodes_cfg->node[i].port == MODBUS_TCP || nodes_cfg->node[i].port == TCP_CLIENT || nodes_cfg->node[i].port == TCPDUMP ||
                (nodes_cfg->node[i].port >= REMOTE_CH_01 && nodes_cfg->node[i].port <= REMOTE_CH_20))
            {
                GET_JSON_VALUE_STRING(node, "tcp_ip_addr", nodes_cfg->node[i].tcp_ip_addr);
                GET_JSON_VALUE_STRING(node, "tcp_port", buff);
                sscanf(buff, "%d", &nodes_cfg->node[i].tcp_port);
            }
            GET_JSON_VALUE_STRING(node, "term_addr", buff);
            if (nodes_cfg->node[i].port == LORA_1) //
            {
                int t = sscanf(buff, "%02X", &addr[1]);
                if (t >= 1)
                {
                    nodes_cfg->node[i].term_addr[0] = 0;
                    nodes_cfg->node[i].term_addr[1] = addr[1];
                    nodes_cfg->node[i].term_addr_len = 2;
                }
            }
            else
            {
                int cnt;
                cnt = sscanf(buff, "%02X%02X%02X%02X%02X%02X%02X%02X", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], &addr[6], &addr[7]);
                for (m = 0; m < cnt && m < 8; m++)
                {
                    nodes_cfg->node[i].term_addr[m] = addr[m];
                }
                nodes_cfg->node[i].term_addr_len = m;
            }
            GET_JSON_VALUE_INT(node, "calculate_window", nodes_cfg->node[i].calculate_window);

            cJSON *params = cJSON_GetObjectItem(node, "refer_param");
            if (params)
            {
                nodes_cfg->node[i].referCnt = cJSON_GetArraySize(params);
                nodes_cfg->node[i].pparam = malloc(sizeof(refer_param_t) * nodes_cfg->node[i].referCnt);
                if (nodes_cfg->node[i].referCnt && nodes_cfg->node[i].pparam == NULL)
                {
                    dy_syslog(LOG_ERR, "nodes_cfg->node[%d].referCnt %d,nodes_cfg->node[%d].pparam %p",
                              i, nodes_cfg->node[i].referCnt, i,
                              nodes_cfg->node[i].pparam);
                    continue;
                }
                memset(nodes_cfg->node[i].pparam, 0, sizeof(refer_param_t) * nodes_cfg->node[i].referCnt);
                for (m = 0; m < nodes_cfg->node[i].referCnt; m++)
                {
                    cJSON *param = cJSON_GetArrayItem(params, m);
                    if (param)
                    {
                        GET_JSON_VALUE_STRING(param, "refer_sn", nodes_cfg->node[i].pparam[m].refer_sn);
                        dy_syslog(LOG_INFO, "nodes_cfg[%d]->param[%d]->refer_sn:%s",
                                  i, m, nodes_cfg->node[i].pparam[m].refer_sn);
                    }
                }
            }
            else
            {
                nodes_cfg->node[i].referCnt = 0;
            }
        }
    }

    nodes_cfg->node_cnt = node_cnt;

out:
    cJSON_Delete(root);
    if (data != NULL)
    {
        free(data);
    }
    if (nodes_cfg == NULL)
    {
        //分配node cnt等于0的node_cfg出来
        nodes_cfg = calloc(1, sizeof(nodes_cfg_table_t));
        nodes_cfg->node_cnt = 0;
    }
    *p_nodes_cfg = nodes_cfg;

    return ret;
}
