#include <stdio.h>
#include <stdlib.h>

#include "ipc_session.h"
#include "dy_utils/dy_common.h"
#include "dy_utils/dy_ipc.h"
#include "cloud_conn_common.h"
#include "dy_utils/protocol.h"
#include "dy_utils/dy_pp.h"

struct sensor_config_t
{
    bool en_limit;
    char *value_name;
    char *alarm_h_name;
    char *alarm_l_name;
    char *limit_h_name;
    char *limit_l_name;
    double limit_h_value;
    double limit_l_value;
}sensor_config_t;

struct sensor_config_t sensor_configs[] =
{
    {false,"door1"},
    {false,"door2"},
    {false,"smoke"},
    {false,"water"},
    {true,"temperature","temp_H","temp_L","Thr_temp_H","Thr_temp_L"},
    {true,"humidity","Hum_H","Hum_L","Thr_Hum_H","Thr_Hum_L"},
};

#ifdef EN_3RD_RTU
struct sensor_config_t rtu_configs[] =
{
    {false,"voltageA"},
    {false,"voltageB"},
    {false,"voltageC"},
    {false,"currentA"},
    {false,"currentB"},
    {false,"currentC"},
    {false,"workmode"},
    {false,"statusK1"},
    {false,"statusK2"},
    {false,"statusK3"},
    {false,"statusK4"},
    {false,"statusK5"},
    {false,"statusK6"},
    {false,"statusK7"},
    {false,"statusK8"},
};
#endif
struct sensor_status_t
{
    double value;
    bool rechange;
    int sign;
    int h_sign;
    int l_sign;
}sensor_status_t;

struct sensor_status_t sensor_status = {0};

int data_report_poll(cloud_conn_var_t *var)
{
    TIMER_CONFIRM(var->report_timer);
}

static void cloud_conn_in_subscribe_all(cloud_conn_var_t *var)
{
    ipc_session_t *ipc_session = var->session;
    char topic[TOPIC_MAX_LEN] = {0};

    snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/+/device/+/data/event/+", var->sn_str);
    ipc_session_subscribe(ipc_session, topic);

    snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/+/device/+/data/service/+", var->sn_str);
    ipc_session_subscribe(ipc_session, topic);
}

char *get_sensor_alarm(cloud_conn_var_t *var)
{
    char *str = NULL;

    bool change = false;
    int i;
    for(i=0; i< ARRAY_SIZE(sensor_configs);i++)
    {
        struct sensor_config_t *sensor_config = &sensor_configs[i];
        struct sensor_status_t *sensor = var->converge_value.getdata(&var->converge_value,sensor_config->value_name);
        if(!sensor)continue;
        if(sensor->rechange)
        {
            sensor->rechange = false;
            var->converge_value.insert(&var->converge_value,sensor_config->value_name,sensor,sizeof(struct sensor_status_t));
            change = true;
        }
    }

    if(change)
    {
        cJSON *root = cJSON_CreateObject();
        for(i=0; i< ARRAY_SIZE(sensor_configs);i++)
        {
            struct sensor_config_t *sensor_config = &sensor_configs[i];
            struct sensor_status_t *sensor = var->converge_value.getdata(&var->converge_value,sensor_config->value_name);
            if(!sensor)continue;
            if(!sensor_config->en_limit)//IO变量
                cJSON_AddStringToObject(root,sensor_config->value_name,sensor->sign?"1":"0");
            else
            {
                cJSON_AddStringToObject(root,sensor_config->alarm_h_name,sensor->h_sign?"1":"0");
                cJSON_AddStringToObject(root,sensor_config->alarm_l_name,sensor->l_sign?"1":"0");
            }
        }
        str = cJSON_Print(root);
        cJSON_Delete(root);
    }
    return str;
}

char *get_sensor_value(cloud_conn_var_t *var)
{
    char *str = NULL;
    cJSON *root = cJSON_CreateObject();
    int i;
    for(i=0; i< ARRAY_SIZE(sensor_configs);i++)
    {
        struct sensor_config_t *sensor_config = &sensor_configs[i];
        struct sensor_status_t *sensor = var->converge_value.getdata(&var->converge_value,sensor_config->value_name);
        if(!sensor)continue;
        char buff[100];
        int len;
        if(!sensor_config->en_limit)//IO变量
            len = snprintf(buff,sizeof(buff),"%d",!!sensor->value);
        else
            len = snprintf(buff,sizeof(buff),"%.2f",sensor->value);

        if (len > 0)cJSON_AddStringToObject(root,sensor_config->value_name,buff);
    }
    str = cJSON_Print(root);
    cJSON_Delete(root);
    return str;
}
#ifdef EN_3RD_RTU
char *get_3rd_rtu_value(cloud_conn_var_t *var)
{
    char *str = NULL;
    cJSON *root = cJSON_CreateObject();
    int i;
    bool found = false;
    for(i=0; i< ARRAY_SIZE(rtu_configs);i++)
    {
        struct sensor_config_t *rtu_config = &rtu_configs[i];
        struct sensor_status_t *rtu = var->converge_value.getdata(&var->converge_value,rtu_config->value_name);
        if(!rtu)continue;
        // cJSON_AddStringToObject(root,rtu_config->value_name,buff);
        found = true;
        cJSON_AddNumberToObject(root,rtu_config->value_name,rtu->value);
    }
    if(!found)
    {
        cJSON_Delete(root);
        return NULL;
    }
    str = cJSON_Print(root);
    cJSON_Delete(root);
    return str;
}
#endif
void effect_limit_config(cloud_conn_var_t *var,char *str)
{
    cJSON *root = cJSON_Parse(str);
    int i;
    for(i=0; i< ARRAY_SIZE(sensor_configs);i++)
    {
        struct sensor_config_t *sensor_config = &sensor_configs[i];
        if(!sensor_config->en_limit)continue;//IO变量
        cJSON *limit_h = cJSON_GetObjectItem(root,sensor_config->limit_h_name);
        if(limit_h) sensor_config->limit_h_value = limit_h->valuedouble;
        cJSON *limit_l = cJSON_GetObjectItem(root,sensor_config->limit_l_name);
        if(limit_l) sensor_config->limit_l_value = limit_l->valuedouble;
    }
    cJSON_Delete(root);
}


static int cloud_conn_internal_mqtt_handle_recv_msg(void *obj, ipc_msg_t *mqtt_msg)
{
    cloud_conn_var_t *var = (cloud_conn_var_t *)obj;

    if (1)
    {
        if(!mqtt_msg->payload) return 0;
        cJSON *root = cJSON_Parse(mqtt_msg->payload);
        cJSON *tag_node = cJSON_GetObjectItem(root,"tag_node");
        if(tag_node && tag_node->valuestring)
        {
            int i;
            cJSON *root_sub = cJSON_Parse(tag_node->valuestring);
            cJSON *identifier = cJSON_GetObjectItem(root,"identifier");
            if(identifier && identifier->valuestring && !strcmp(identifier->valuestring,"get_jpg")) //图片抓拍
            {
                cJSON *jpg_url = cJSON_GetObjectItem(root_sub,"jpg_url");
                if(jpg_url && jpg_url->valuestring)
                {
                    list_pic_path *tmp = malloc(sizeof(list_pic_path));
                    if(tmp)
                    {
                        tmp->path = strdup(jpg_url->valuestring);
                        dy_syslog(LOG_INFO, "recv picture signal, path %s",tmp->path);
                        pthread_mutex_lock(&var->mx_path);
                        list_add_tail(&tmp->list,&var->l_path);
                        pthread_mutex_unlock(&var->mx_path);
                    }
                }
            }
            else // 其他传感器
            {
            for(i=0; i< ARRAY_SIZE(sensor_configs);i++)
            {
                struct sensor_config_t *sensor_config = &sensor_configs[i];
                //dy_syslog(LOG_INFO, "key:%s", sensor_config->value_name);
                cJSON *name = cJSON_GetObjectItem(root_sub,sensor_config->value_name);
                if(name)
                {
                    int last_sign = 0;
                    struct sensor_status_t tmp={0};
                    struct sensor_status_t *sensor = var->converge_value.getdata(&var->converge_value,sensor_config->value_name);
                    if(!sensor)
                        sensor = &tmp;
                    dy_syslog(LOG_INFO, "getdata [%s] value:%f sign:%d sign_h:%d sign_l:%d",sensor_config->value_name, sensor->value,sensor->sign,sensor->h_sign,sensor->l_sign);
                    sensor->value =  name->valuedouble;
                    //修改报警标记
                    if(sensor_config->en_limit) //模拟量
                    {
                        dy_syslog(LOG_INFO, "getdata [%s] value:%f limit:%f",sensor_config->value_name, sensor_config->limit_h_value);
                        if(sensor->value > sensor_config->limit_h_value)last_sign = 1;
                        else    last_sign = 0;

                        if(last_sign != sensor->h_sign)//判断变更与否
                        {
                            sensor->h_sign = last_sign;
                            sensor->rechange = true;
                        }

                        if(sensor->value < sensor_config->limit_l_value)last_sign = 1;
                        else    last_sign = 0;

                        if(last_sign != sensor->l_sign)//判断变更与否
                        {
                            sensor->l_sign = last_sign;
                            sensor->rechange = true;
                        }

                    }
                    else //IO量
                    {
                        sensor->sign = sensor->value;
                        last_sign = sensor->value;
                        if(last_sign != sensor->sign)//判断变更与否
                            sensor->sign = last_sign;
                            sensor->rechange = true;
                    }
                    var->converge_value.insert(&var->converge_value,sensor_config->value_name,sensor,sizeof(struct sensor_status_t));
                }
            }

#ifdef EN_3RD_RTU
            for(i=0; i< ARRAY_SIZE(rtu_configs);i++)
            {
                struct sensor_config_t *rtu_config = &rtu_configs[i];
                //dy_syslog(LOG_INFO, "key:%s", rtu_config->value_name);
                cJSON *name = cJSON_GetObjectItem(root_sub,rtu_config->value_name);
                if(name)
                {
                    int last_sign = 0;
                    struct sensor_status_t tmp={0};
                    struct sensor_status_t *rtu = &tmp;
                    dy_syslog(LOG_INFO, "getdata [%s] value:%f sign:%d sign_h:%d sign_l:%d",rtu_config->value_name, rtu->value,rtu->sign,rtu->h_sign,rtu->l_sign);
                    rtu->value =  name->valuedouble;
                    var->converge_value.insert(&var->converge_value,rtu_config->value_name,rtu,sizeof(struct sensor_status_t));
                }
            }
#endif
            }
        }
        cJSON_Delete(root);
    }
    return 0;
}

// 建立与内部broker之间的MQTT连接
int cloud_conn_internal_mqtt_init(cloud_conn_var_t *var)
{
    char clientId[MAX_CLIENT_ID_LEN] = {0};

    snprintf(clientId, MAX_CLIENT_ID_LEN, "INT_DY_CLD2_%s", var->sn_str);
    var->session = ipc_session_new(clientId, (void*)var, IPC_DEFAULT);
    if (var->session == NULL) return -1;

    ipc_session_set_callbacks(var->session, cloud_conn_internal_mqtt_handle_recv_msg, NULL);
    cloud_conn_in_subscribe_all(var);
    ipc_session_start(var->session);
    kv_array_init(&var->converge_value,20);
}
