#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <poll.h>

#include "cloud_emmsv2_common.h"
#include "dy_utils/protocol.h"

static void cloud_emmsv2_connredis(redisContext **connContext)
{
    while(true)
    {
        *connContext = redisConnect(REDIS_SERVER_IP, REDIS_SERVER_PORT);
        if ((*connContext)->err)
        {
            dbg_syslog(LOG_ERR, "connect redis server failure: %s\n", (*connContext)->errstr);
            redisFree(*connContext);
            usleep(10 * 1000 * 1000); //等待10s让redis server启动
        }
        else
        {
            dbg_syslog(LOG_NOTICE, "connect redis server success");
            break;
        }
    }
}

static void cloud_emmsv2_getstainfo(cloud_emmsv2_var_t *var)
{
    snprintf(var->lcid, MAX_ID_LEN, "2402260001");
    snprintf(var->lcsta, MAX_STA_LEN, "346.66,568.88");
    var->capacity = 900;
    var->power = 400;
    snprintf(var->loadtime, MAX_LOADTIME_LEN, "2024-02-01");
    snprintf(var->loc, MAX_LOC_LEN, "浙江省杭州市");
    snprintf(var->staname, MAX_STAN_LEN, "默认站点名称");
    snprintf(var->vendor, MAX_VEND_LEN, "LNXALL");
    snprintf(var->softver, MAX_SFVER_LEN, "5.375.1736");
    snprintf(var->model, MAX_MODEL_LEN, "IMX6ULL");
}

static void cloud_emmsv2_loop(cloud_emmsv2_var_t *var)
{
    int ret = 0;
    struct pollfd pfd;
    struct timespec tspec;

    while (1)
    {
        pfd.fd = var->status_timer;
        pfd.events = POLLIN;
        pfd.revents = 0;
        if (pfd.fd > 0)
            ret = poll(&pfd, 0x1, 1000);
        else {
            tspec.tv_sec = 5;
            tspec.tv_nsec = 0;
            nanosleep(&tspec, NULL);
        }
        if (ret < 0)
        {
            int error = errno;
            printf("errno %d\n", error);
            if (error == EINTR)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else if (ret > 0)
        {
            if (var->status_timer > 0 && pfd.revents)
            {
                comm_status_poll(var);
            }
        }
    }
}

static void cloud_emmsv2_stacfg_int(cloud_emmsv2_var_t *var, char *cfg_file)
{
    char *data = NULL;
    cJSON *root = NULL;
    int lens;

    if (cfg_file == NULL)
    {
        dbg_syslog(LOG_ERR, "cfg_file:%s not exist, use defaut MQTT server", cfg_file);
        return;
    }

    data = read_file_data_and_lens(cfg_file, &lens);
    if (data == NULL)
    {
        dbg_syslog(LOG_ERR, "read cfg file %s error, load default", cfg_file);
        return;
    }

    root = cJSON_Parse(data);
    if (!root)
    {
        dbg_syslog(LOG_ERR, "parse cfg file %s error, load default", cfg_file);
        return;
    }

    GET_JSON_VALUE_STRING(root, "protocolVer", var->protocolVer);
    GET_JSON_VALUE_INT(root, "mode", var->mode);
    GET_JSON_VALUE_STRING(root, "id", var->lcid);
    GET_JSON_VALUE_STRING(root, "station", var->lcsta);
    GET_JSON_VALUE_INT(root, "capacity", var->capacity);
    GET_JSON_VALUE_INT(root, "power", var->power);
    GET_JSON_VALUE_STRING(root, "time", var->loadtime);
    GET_JSON_VALUE_STRING(root, "local", var->loc);
    GET_JSON_VALUE_STRING(root, "station_name", var->staname);
    GET_JSON_VALUE_STRING(root, "vendor", var->vendor);
    GET_JSON_VALUE_STRING(root, "softVersion", var->softver);
    GET_JSON_VALUE_STRING(root, "tenant_id", var->tenant_id);
    GET_JSON_VALUE_STRING(root, "model", var->model);

    cJSON_Delete(root);
}

static void cloud_emmsv2_tagmap_init(cloud_emmsv2_var_t *var)
{
    char emmstag[MAX_TAG_LEN] = {0};
    char emsctrltag[MAX_TAG_LEN] = {0};
    FILE *fp = fopen(EMMSV2_TAGMAP_CONFIG, "r");
    if (fp == NULL)
    {
        dbg_syslog(LOG_ERR, "open tagmap file failed");
        return;
    }

    while (fscanf(fp, "%s %s", emmstag, emsctrltag)!= EOF)
    {
	    tagmap_entry_t* curtag;
        HASH_FIND_STR(var->tagmaps, emmstag, curtag);
        if (NULL == curtag)
        {
            curtag = malloc(sizeof(tagmap_entry_t));
            snprintf(curtag->emmstag, MAX_TAG_LEN, "%s", emmstag);
            snprintf(curtag->emsctrltag, MAX_TAG_LEN, "%s", emsctrltag);
            HASH_ADD_STR(var->tagmaps, emmstag, curtag);
        }
    }
    fclose(fp);
}

//模块初始化
static int cloud_emmsv2_init(cloud_emmsv2_var_t *var)
{
    char cmd[CMD_SHORT_LENGTH] = {0};
    get_board_sn(var->sn_str);
    get_process_name(var->proc_name);
    get_product_name(var->product_name);
    cloud_emmsv2_getstainfo(var);
    snprintf(var->emsctrl_sn_str, SN_MAX_LEN * 2, "%s_EMSCTRL", var->sn_str);

    dy_syslog(LOG_INFO, "board SN:%s", var->sn_str);

    if (load_nodes_cfg(&var->nodes_cfg_table, NODES_CFG_PATH) == -1)
    {
        dy_syslog(LOG_ERR, "load nodes cfg fail");
    }

    cloud_emmsv2_stacfg_int(var, EMMSV2_STATION_CONFIG);
    cloud_emmsv2_internal_mqtt_init(var);
    cloud_emmsv2_mqtt_init(var);

    dy_syslog(LOG_INFO, "init done");

    //从设置参数表setparam读取当前控制模式，读不到则置初值为1
    cloud_emmsv2_connredis(&var->context);
    snprintf(cmd, CMD_SHORT_LENGTH, "hget "REDIS_SETPARAM_BASE" "SET_CTRLMODE);
    redisReply *reply = (redisReply *)redisCommand(var->context, cmd);
    if (NULL == reply)
    {
        dbg_syslog(LOG_ERR, "execcmd %s error", cmd);
    }
    else if (reply->type == REDIS_REPLY_NIL)
    {
        var->controlMode = -1;
    }
    else
    {
        var->controlMode = atoi(reply->str);        
    }
    freeReplyObject(reply);

    cloud_emmsv2_tagmap_init(var);
    var->db_period = DEF_DB_PERIOD;
    var->db_endtime = time(NULL);

    return 0;
}

int main(int argc, char *argv[])
{
    cloud_emmsv2_var_t var = {0};
    lnxall_loglevel_set(LNXALL_LOGINFO, 1);
    memset(&var, 0, sizeof(var));

    cloud_emmsv2_init(&var);
    post_run_led(LED_TWINKLE);
    post_net_led(LED_TWINKLE);
    cloud_emmsv2_loop(&var);

    return 0;
}
