
#include "ems_activition.h"
#include "define.h"
#include "dy_common.h"
#include "../common.h"
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syslog.h>
#include <time.h>
#include "../multilanguage.h"
#include "g100_protect.h"
#include "../cc_lc_com/define.h"
#include "deviceLayer.h"

static ems_activition_record_t activition_record = {0};

ems_activition_record_t* ems_activition_get_record()
{
    return &activition_record;
}

static void ems_activition_save_record(ems_activition_record_t* record)
{
    if (record == NULL)
    {
        return;
    }

    cJSON* root = cJSON_CreateObject();
    if (root == NULL)
    {
        return;
    }
    char tmp[32] = {0};
    snprintf(tmp, sizeof(tmp), "%lu", record->grid_online_time);
    cJSON_AddStringToObject(root, "grid_online_time", tmp);
    snprintf(tmp, sizeof(tmp), "%lu", record->grid_last_online_time);
    cJSON_AddStringToObject(root, "grid_last_online_time", tmp);
    snprintf(tmp, sizeof(tmp), "%lu", record->power_on_time);
    cJSON_AddStringToObject(root, "power_on_time", tmp);
    snprintf(tmp, sizeof(tmp), "%lu", record->power_last_on_time);
    cJSON_AddStringToObject(root, "power_last_on_time", tmp);
    snprintf(tmp, sizeof(tmp), "%lu", record->activition_time);
    cJSON_AddStringToObject(root, "activition_time", tmp);
    cJSON_AddBoolToObject(root, "is_activition", atomic_load(&record->is_activition));
    cJSON_AddBoolToObject(root, "is_report", record->is_report);

    char* data = cJSON_Print(root);
    if (data != NULL)
    {
        write_file_data(EMS_OPERATION_RECORD_FILE, data, strlen(data));
        free(data);
    }
    cJSON_Delete(root);
}

static void* ems_activition_set_time_thread(void* arg)
{
    ems_activition_record_t* record = (ems_activition_record_t*)arg;
    if (record == NULL)
    {
        return NULL;
    }

    while (true)
    {
        sleep(1);
        time_t now = time(NULL);

        int online = dev_get_dev_tag_int(DEV_NO_GRID_MT, STATE_ONLINE);
        if (online == 1)
        {
            if (now - record->grid_last_online_time > EMS_OPERATION_OFFLINE_TIME)
            {
                ems_syslog(LOG_WARNING, "关口表离线时间超过 %d s, 重新计时", EMS_OPERATION_OFFLINE_TIME);
                record->grid_online_time = now;
            }
            else if (now - record->grid_online_time > EMS_OPERATION_GRID_ONLINE_TIME)
            {
                ems_syslog(LOG_INFO, "关口表在线时间超过 %d s, 设置操作时间", EMS_OPERATION_GRID_ONLINE_TIME);
                record->activition_time = now;
                atomic_store(&record->is_activition, true);
            }
            record->grid_last_online_time = now;
        }

        int power_on = dev_get_dev_tag_int(DEV_NO_EMS, EMS_POWER);
        if (power_on == 0)
        {
            if (now - record->power_last_on_time > EMS_OPERATION_POWER_OFF_TIME)
            {
                ems_syslog(LOG_WARNING, "控制器离线时间超过 %d s, 重新计时", EMS_OPERATION_OFFLINE_TIME);
                record->power_on_time = now;
            }
            else if (now - record->power_on_time > EMS_OPERATION_POWER_ON_TIME)
            {
                ems_syslog(LOG_INFO, "控制器上电时间超过 %d s, 设置操作时间", EMS_OPERATION_POWER_ON_TIME);
                record->activition_time = now;
                atomic_store(&record->is_activition, true);
            }
            record->power_last_on_time = now;
        }
        
        if (atomic_load(&record->is_activition) == true || now - record->last_save_time > EMS_OPERATION_SAVE_INTERVAL)
        {
            record->last_save_time = now;
            ems_activition_save_record(record);

            if (atomic_load(&record->is_activition) == true)
            {
                ems_syslog(LOG_INFO, "设备已启用, 设置启用时间 %ld", now);
                break;
            }
        }
    }

    return NULL;
}

int init_activition_record(void)
{
    ems_activition_record_t* record = &activition_record;
    memset(record, 0, sizeof(ems_activition_record_t));

    cJSON* root = NULL;
    char*  data = read_file_data(EMS_OPERATION_RECORD_FILE);
    if (data != NULL)
    {
        ems_syslog(LOG_WARNING, "read file %s failed", EMS_OPERATION_RECORD_FILE);
        root = cJSON_Parse(data);
    }
    if (root == NULL)
    {
        root = cJSON_CreateObject();
    }
    cJSON* is_activition = cJSON_GetObjectItem(root, "is_activition");
    if( is_activition != NULL && is_activition->valueint == 1)
    {
        atomic_store(&record->is_activition, true);
        cJSON* activition = cJSON_GetObjectItem(root, "activition_time");
        if (activition != NULL && activition->valuestring != NULL)
        {
            record->activition_time = atol(activition->valuestring);
        }
        else
        {
            record->activition_time = time(NULL);
        }
    }
    else
    {
        atomic_store(&record->is_activition, false);
        cJSON* grid_online_time = cJSON_GetObjectItem(root, "grid_online_time");
        if (grid_online_time != NULL && grid_online_time->valuestring != NULL)
        {
            record->grid_online_time = atol(grid_online_time->valuestring);
        }

        cJSON* grid_last_online_time = cJSON_GetObjectItem(root, "grid_last_online_time");
        if (grid_last_online_time != NULL && grid_last_online_time->valuestring != NULL)
        {
            record->grid_last_online_time = atol(grid_last_online_time->valuestring);
        }
        cJSON* power_on_time = cJSON_GetObjectItem(root, "power_on_time");
        if (power_on_time != NULL && power_on_time->valuestring != NULL)
        {
            record->power_on_time = atol(power_on_time->valuestring);
        }
        cJSON* power_last_on_time = cJSON_GetObjectItem(root, "power_last_on_time");
        if (power_last_on_time != NULL && power_last_on_time->valuestring != NULL)
        {
            record->power_last_on_time = atol(power_last_on_time->valuestring);
        }
    }

    cJSON* report = cJSON_GetObjectItem(root, "is_report");
    if (report != NULL)
    {
        record->is_report = report->valueint;
    }

    if (atomic_load(&record->is_activition) == true)
    {
        ems_syslog(LOG_INFO, "ems activition time has setted, timestr: %ld", record->activition_time);
    }
    else
    {
        pthread_t tid;
        pthread_create(&tid, NULL, ems_activition_set_time_thread, record);
        pthread_detach(tid);
    }

    if (root) cJSON_Delete(root);
    if (data) free(data);
    return 0;
}

int ems_activition_set_time(time_t t, int type) // 0 : 正常
{
    if (type != 0)
    {
        time_t now = time(NULL);
        if (t == 0 || t > now)
        {
            return -1;
        }
        atomic_store(&activition_record.is_activition, true);
        activition_record.activition_time = t;
    }
    ems_activition_save_record(&activition_record);
    return 0;
}

int ua_set_activition(char* result)
{
    if (atomic_load(&activition_record.is_activition) == true)
    {
        int        len = sprintf(result, "设备已启用, 启用时间: ");

        struct tm target_time = {};  
        localtime_r(&activition_record.activition_time, &target_time);
        struct tm *l = &target_time;

        strftime(result + len, 64, "%Y-%m-%d %H:%M:%S", l);
        return -1;
    }

    time_t now = time(NULL);
    ems_activition_set_time(now, 1);
    sprintf(result, "设备已启用");
    return 0;
}

time_t ems_activition_get_time()
{
    return atomic_load(&activition_record.is_activition) ? activition_record.activition_time : -1;
}

int read_activition_time(char* name, void* value_v)
{
    cJSON* root         = NULL;
    cJSON* is_activition    = NULL;
    cJSON* activition_time = NULL;
    char   time_str[128] = {0};
    char*  data         = read_file_data(EMS_OPERATION_RECORD_FILE);
    int    ret          = -1;
    if (data == NULL)
    {
        ems_syslog(LOG_WARNING, "read file %s failed", EMS_OPERATION_RECORD_FILE);
        goto END;
    }
    root = cJSON_Parse(data);
    if (root == NULL)
    {
        goto END;
    }
    is_activition = cJSON_GetObjectItem(root, "is_activition");
    activition_time = cJSON_GetObjectItem(root, "activition_time");

    if( is_activition == NULL || is_activition->valueint == 0)
    {
        sprintf(time_str, "%s", _("Not activition"));
        goto END;
    }
    else if (activition_time == NULL || activition_time->valuestring == 0)
    {
        sprintf(time_str, "%s", _("Not activition"));
        goto END;
    }
    else
    {
        time_t     t = atol(activition_time->valuestring);
        if(t == 0)
        {
            sprintf(time_str, "%s", _("Not activition"));
            goto END;
        }
 
        struct tm target_time = {};  
        localtime_r(&t, &target_time);
        struct tm *l = &target_time;

        int len = sprintf(time_str, "%s", _("Activited, "));
        strftime(time_str + len, sizeof(time_str) - len, " %Y-%m-%d %H:%M:%S", l);
    }
END:
    strcpy(value_v, time_str);
    if (data) free(data);
    if (root) cJSON_Delete(root);
    return ret;
}
