#include "energy_config.h"

static int pcs_count = 0;
static int scale_factor_count = 0;

static void print_cfg_load_result(energy_var_t *var)
{
    if (var == NULL) {
        dbg_syslog(LOG_ERR, "invalid argument!");
        return;
    }

    dbg_syslog(LOG_NOTICE, "----------------eng_ass----------------");
    dbg_syslog(LOG_NOTICE, "eng_ass_grp_num: %d", var->eng_ass_grp_num);
    for (int i = 0; i < var->eng_ass_grp_num; i++) {
        dbg_syslog(LOG_NOTICE, "pcs_sn[%d]       : %s", i, var->grp[i].eng_ass_grp_cfg.pcs_sn);
        dbg_syslog(LOG_NOTICE, "pcs_belong_gw[%d]: %s", i, var->grp[i].eng_ass_grp_cfg.belong_gw);
        dbg_syslog(LOG_NOTICE, "pcs[%d] scale_factor: %d", i, var->grp[i].eng_ass_grp_cfg.scale_factor);
        dbg_syslog(LOG_NOTICE, "bms_dev_num[%d]  : %d", i, var->grp[i].eng_ass_grp_cfg.bms_dev_num);
        for (int j = 0; j < var->grp[i].eng_ass_grp_cfg.bms_dev_num; j++) {
            dbg_syslog(LOG_NOTICE, "bms_sn[%d:%d]       : %s",i, j, var->grp[i].eng_ass_grp_cfg.bms_sn[j]);
            dbg_syslog(LOG_NOTICE, "bms_belong_gw[%d:%d]: %s",i, j, var->grp[i].eng_ass_grp_cfg.bms_belong_gw[j]);
        }
    }
    dbg_syslog(LOG_NOTICE, "---------------------------------------");
}

static void add_data_struct(energy_var_t *var, cJSON *node, eng_ass_grp_cfg_t *cfg)
{
    cJSON *type = cJSON_GetObjectItem(node, "type");
        dbg_syslog(LOG_INFO, "type:%s",type->valuestring);
    if( strcmp(type->valuestring,"pcs") == 0)
    {
        GET_JSON_VALUE_DY_STRING(node, "dev_sn", cfg->pcs_sn);
        GET_JSON_VALUE_DY_STRING(node, "belong_gw", cfg->belong_gw);
        hash_intptr_addptr(&var->sub_gw_sn_map, cfg->pcs_sn, strlen(cfg->pcs_sn), cfg->belong_gw);
        pcs_count++;
        GET_JSON_VALUE_INT(node, "scale_factor", cfg->scale_factor);
        if (cfg->scale_factor == NULL)
        {
            cfg->scale_factor = 1;
        }
        scale_factor_count = scale_factor_count + cfg->scale_factor;
    }
    else if( strcmp(type->valuestring,"meter") == 0)
    {
        GET_JSON_VALUE_DY_STRING(node, "dev_sn", cfg->meter_sn);
        GET_JSON_VALUE_DY_STRING(node, "belong_gw", cfg->belong_gw);
        hash_intptr_addptr(&var->sub_gw_sn_map, cfg->meter_sn, strlen(cfg->meter_sn), cfg->belong_gw);
    }
    else if( strcmp(type->valuestring,"cluster") == 0)
    {
        GET_JSON_VALUE_DY_STRING(node, "dev_sn", cfg->bms_sn[cfg->bms_dev_num]);
        GET_JSON_VALUE_DY_STRING(node, "belong_gw", cfg->bms_belong_gw[cfg->bms_dev_num]);
        hash_intptr_addptr(&var->sub_gw_sn_map, cfg->bms_sn[cfg->bms_dev_num], strlen(cfg->bms_sn[cfg->bms_dev_num]), cfg->bms_belong_gw[cfg->bms_dev_num]);
        (cfg->bms_dev_num)++;
    }
}
//added by yut
void energy_state_config(energy_var_t *var,char *cfg_file)
{
    char *pdata = NULL;
    cJSON *root = NULL;
    pdata = read_file_data(cfg_file);
    if (pdata == NULL)
    {
        dbg_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        goto out;
    }
    root = cJSON_Parse(pdata);
    if (!root)
    {
        dbg_syslog(LOG_ERR, "parse pdata %s error", pdata);
        goto out;
    }
    GET_JSON_VALUE_INT(root, "on_service_state",var->eng_ass_data->on_service_state);
    dbg_syslog(LOG_NOTICE, "on_service_state %d ", var->eng_ass_data->on_service_state);
    GET_JSON_VALUE_INT(root, "expect_run_state",var->eng_ass_data->expect_run_state);
    dbg_syslog(LOG_NOTICE, "expect_run_state %d ", var->eng_ass_data->expect_run_state);
    GET_JSON_VALUE_INT(root, "expect_relay_state",var->eng_ass_data->expect_relay_state);
    dbg_syslog(LOG_NOTICE, "expect_relay_state %d ", var->eng_ass_data->expect_relay_state);
    GET_JSON_VALUE_INT(root, "pcs_connect_state",var->eng_ass_data->pcs_connect_state);
    dbg_syslog(LOG_NOTICE, "pcs_connect_state %d ", var->eng_ass_data->pcs_connect_state);
    //GET_JSON_VALUE_INT(root, "expect_power",var->eng_ass_data->expect_power);
    var->eng_ass_data->expect_power = 0;//手动模式下设置功率后重启，会按照最后一次设置的值继续执行，因此重启后需清0
    var->eng_ass_data->expect_wggl = 0;
    dbg_syslog(LOG_NOTICE, "expect_power %d ", var->eng_ass_data->expect_power);
    GET_JSON_VALUE_DOUBLE(root, "SOCMAX",var->eng_ass_data->SOCMAX);
    dbg_syslog(LOG_NOTICE, "SOCMAX %f ", var->eng_ass_data->SOCMAX);
    GET_JSON_VALUE_DOUBLE(root, "SOCMIN",var->eng_ass_data->SOCMIN);
    dbg_syslog(LOG_NOTICE, "SOCMIN %f ", var->eng_ass_data->SOCMIN);
    if (var->eng_ass_data->SOCMAX == 0 && var->eng_ass_data->SOCMIN == 0)
    {
        var->eng_ass_data->SOCMAX = -1;
        var->eng_ass_data->SOCMIN = -1;
    }
    GET_JSON_VALUE_DOUBLE(root, "SINGLE_MAX",var->eng_ass_data->SINGLE_MAX);
    dbg_syslog(LOG_NOTICE, "SINGLE_MAX %f ", var->eng_ass_data->SINGLE_MAX);
    GET_JSON_VALUE_DOUBLE(root, "SINGLE_MIN",var->eng_ass_data->SINGLE_MIN);
    dbg_syslog(LOG_NOTICE, "SINGLE_MIN %f ", var->eng_ass_data->SINGLE_MIN);
    if (var->eng_ass_data->SINGLE_MAX == 0 && var->eng_ass_data->SINGLE_MIN == 0)
    {
        var->eng_ass_data->SINGLE_MAX = -1;
        var->eng_ass_data->SINGLE_MIN = -1;
    }

    abstract_item_t *item = var->module_item;
    if(item)
    {
        if(item->set_service_state)item->set_service_state(var,var->eng_ass_data->on_service_state);
        if(item->set_runmode)item->set_runmode(var,var->eng_ass_data->expect_run_state);
        if(item->set_bms_relay)item->set_bms_relay(var,var->eng_ass_data->expect_relay_state);
        if(item->set_pcs_connect)item->set_pcs_connect(var,var->eng_ass_data->pcs_connect_state);
        if(item->set_total_power)item->set_total_power(var,var->eng_ass_data->expect_power,0);
        if(item->set_total_power)item->set_total_power(var,var->eng_ass_data->expect_wggl,1);
    }
    // var->grp[0].eng_ass_grp_ctrl.relay = var->eng_ass_data->expect_relay_state;
    out:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }


}
//ended by yut

void energy_state_config_load_ems(energy_var_t *var,char *cfg_file)
{
    char *pdata = NULL;
    cJSON *root = NULL;
    pdata = read_file_data(cfg_file);
    if (pdata == NULL)
    {
        dbg_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        goto out;
    }
    root = cJSON_Parse(pdata);
    if (!root)
    {
        dbg_syslog(LOG_ERR, "parse pdata %s error", pdata);
        goto out;
    }
    GET_JSON_VALUE_INT(root, "runState",var->ems_run_mode);
    dbg_syslog(LOG_NOTICE, " ems_run_mode %d ", var->ems_run_mode);

    out:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }
}
void energy_state_config_load_ems_cfg(energy_var_t *var,char *cfg_file)
{
    char *pdata = NULL;
    cJSON *root = NULL;
    pdata = read_file_data(cfg_file);
    if (pdata == NULL)
    {
        dbg_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        goto out;
    }
    root = cJSON_Parse(pdata);
    if (!root)
    {
        dbg_syslog(LOG_ERR, "parse pdata %s error", pdata);
        goto out;
    }
    GET_JSON_VALUE_INT(root, "supportStandy",var->supportStandy);
    dbg_syslog(LOG_NOTICE, " support Standy %d ", var->supportStandy);

    out:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }
}

void energy_load_config(energy_var_t *var, char *cfg_file)
{
    char *pdata = NULL;
    cJSON *node = NULL;
    cJSON *child_node = NULL;
    cJSON *child_nodes = NULL;
    cJSON *root = NULL;
    cJSON *nodes = NULL;
    pdata = read_file_data(cfg_file);

    if (pdata == NULL)
    {
        dbg_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        goto out;
    }

    root = cJSON_Parse(pdata);
    if (!root)
    {
        dbg_syslog(LOG_ERR, "parse pdata %s error", pdata);
        goto out;
    }

    nodes = cJSON_GetObjectItemCaseSensitive(root, "groups");

    if (!nodes)
    {
        dbg_syslog(LOG_ERR, "get groups node failed");
        goto out;
    }
    int node_cnt = cJSON_GetArraySize(nodes);

    if (node_cnt != 0)
    {
        for (int i = 0; i < node_cnt; i++)
        {
            node = cJSON_GetArrayItem(nodes, i);
            add_data_struct(var,node, &var->grp[i].eng_ass_grp_cfg);
            if (cJSON_GetObjectItemCaseSensitive(node, "child_devs"))
            {

                child_nodes = cJSON_GetObjectItem(node, "child_devs");
                int child_nodes_cnt = cJSON_GetArraySize(child_nodes);

                for (int j = 0; j < child_nodes_cnt; j++)
                {
                    child_node = cJSON_GetArrayItem(child_nodes, j);
                    add_data_struct(var,child_node, &var->grp[i].eng_ass_grp_cfg);
                }
            }
        }
    }
    var->eng_ass_grp_num = pcs_count;
    var->scale_factor_total_num = scale_factor_count;
    GET_JSON_VALUE_INT_LOG(root, "runMode", var->runMode);
    if (var->runMode == E_ONIOTBOX_MODE)
    {
        nodes = cJSON_GetObjectItemCaseSensitive(root, "mqtt");
        if (!nodes)
        {
            dbg_syslog(LOG_ERR, "get mqtt_broker failed");
            goto out;
        }
        GET_JSON_VALUE_STRING_LOG(nodes, "host", var->mqttBroker.hostname);
        GET_JSON_VALUE_STRING_LOG(nodes, "user", var->mqttBroker.username);
        GET_JSON_VALUE_STRING_LOG(nodes, "passwd", var->mqttBroker.password);
        GET_JSON_VALUE_INT_LOG(nodes, "port", var->mqttBroker.port);
    }
    var->dev_online_timeout = 0;
    GET_JSON_VALUE_INT_LOG(root, "online_timeout", var->dev_online_timeout);
    print_cfg_load_result(var);
out:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }
}

void energy_load_config_from_ems_structure(energy_var_t *var, char *cfg_file)
{
    char *pdata = NULL;
    cJSON *storage = NULL;
    cJSON *node = NULL;
    cJSON *child_dev = NULL;
    cJSON *child_devs = NULL;
    cJSON *root = NULL;
    cJSON *nodes = NULL;
    char type[32] = {'\0'};

    if (var == NULL || cfg_file == NULL) {
        dbg_syslog(LOG_ERR, "invalid argument! var: %p cfg_file: %p", var, cfg_file);
        goto out;
    }

    dbg_syslog(LOG_NOTICE, "cfg_file: %s", cfg_file);
    pdata = read_file_data(cfg_file);
    if (pdata == NULL) {
        dbg_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        goto out;
    }

    root = cJSON_Parse(pdata);
    if (!root) {
        dbg_syslog(LOG_ERR, "parse pdata %s error", pdata);
        goto out;
    }

    storage = cJSON_GetObjectItemCaseSensitive(root, "storage");
    if (!storage) {
        dbg_syslog(LOG_ERR, "get object storage error");
        goto out;
    }

    int dev_cnt = cJSON_GetArraySize(storage);
    int pcs_idx = 0;
    for (int i = 0; i < dev_cnt; i++) {
        cJSON *dev = cJSON_GetArrayItem(storage, i);
        if (dev == NULL) {
            dbg_syslog(LOG_ERR, "cJSON_GetArrayItem() failed!");
            goto out;
        }

        GET_JSON_VALUE_STRING_LOG(dev, "type", type);
        if (strcmp(type, "pcs") != 0) {
            continue;
        }        
        add_data_struct(var, dev, &var->grp[pcs_idx].eng_ass_grp_cfg);
        
        child_devs = cJSON_GetObjectItemCaseSensitive(dev, "child_devs");
        if (child_devs == NULL) {
            continue;
        }

        int child_devs_cnt = cJSON_GetArraySize(child_devs);
        for (int j = 0; j < child_devs_cnt; j++)
        {
            child_dev = cJSON_GetArrayItem(child_devs, j);
            add_data_struct(var, child_dev, &var->grp[pcs_idx].eng_ass_grp_cfg);
        }
        pcs_idx = pcs_idx + 1;
    }
    var->eng_ass_grp_num = pcs_count;
    var->scale_factor_total_num = scale_factor_count;

    print_cfg_load_result(var);
out:
    if (root != NULL)
    {
        cJSON_Delete(root);
    }
    if (pdata != NULL)
    {
        free(pdata);
    }
}
