#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include "jsonp.h"
#include "emsctrl.h"
#include "emsctrlProc.h"

extern CHARGE_MNG_INFO_T g_charge_mng_info;

extern PCS_CFG_T g_pcs_cfg_info;

extern STRATEGY_MNG_T g_strategr_mng_info;

bool is_charge(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.planInfo.option == E_CHARGE_DOING);
}

bool is_discharge(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.planInfo.option == E_CHAREG_DISCH);
}

bool is_idle(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.planInfo.option == E_CHARGE_IDLE);
}

bool is_off(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.planInfo.option == E_CHARGE_STOP);
}


bool is_pcs_fault(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.pcserr != 0);
}

bool is_bms_fault(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.bmserr != 0);
}

bool is_aux_fault(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.ioinfo.surge_io_in_line \
    || g_charge_mng_info.ioinfo.surge_io_in_station \
    || g_charge_mng_info.ioinfo.smog_io_state \
    || g_charge_mng_info.ioinfo.temp_io_state \
    || g_charge_mng_info.ioinfo.gas_io_state \
    || g_charge_mng_info.ioinfo.fire_io_state \
    );
}

bool is_not_pcs_fault(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.pcserr == 0);
}

bool is_not_aux_fault(pcs_ctrl_var_t *var)
{
    return !(g_charge_mng_info.ioinfo.surge_io_in_line \
    || g_charge_mng_info.ioinfo.surge_io_in_station \
    || g_charge_mng_info.ioinfo.smog_io_state \
    || g_charge_mng_info.ioinfo.temp_io_state \
    || g_charge_mng_info.ioinfo.gas_io_state \
    || g_charge_mng_info.ioinfo.fire_io_state \
    );
}

bool is_not_bms_fault(pcs_ctrl_var_t *var)
{
    return (g_charge_mng_info.bmserr == 0);
}

bool is_connect(pcs_ctrl_var_t *var)
{
    return g_charge_mng_info.ioinfo.grid_io_state == E_OFF;
}

bool is_disconnect(pcs_ctrl_var_t *var)
{
    return g_charge_mng_info.ioinfo.grid_io_state == E_ON;
}



/*****************************************************/
/*********************条件触发后执行动作*********************/
/*****************************************************/
int wrap_pcs_onoff(pcs_ctrl_var_t *var,act_func_param_t param)
{
    if(param.n1 == E_OFF)
        pcs_dev_close(var);
    else if(param.n1 == E_ON)
        pcs_dev_open(var);
    else
        return 1;
    return 0;
}


int wrap_standby(pcs_ctrl_var_t *var,act_func_param_t param)
{
    pcs_dev_standby_set(var);
    return 0;
}


int wrap_pcs_power(pcs_ctrl_var_t *var,act_func_param_t param)
{
    pcs_dev_yggl_set(var, param.n1);
    return 0;
}

int wrap_pcs_zero_power(pcs_ctrl_var_t *var,act_func_param_t param)
{
    pcs_dev_yggl_set(var, param.n1);
    return 0;
}

int wrap_pcs_disconnect(pcs_ctrl_var_t *var,act_func_param_t param)
{
    pcs_dev_disconect_set(var);
    return 0;
}

int wrap_pcs_connect(pcs_ctrl_var_t *var,act_func_param_t param)
{
    pcs_dev_connect_set(var);
    return 0;
}

int wrap_ems_mode_set(pcs_ctrl_var_t *var,act_func_param_t param)
{
    if(param.n1 >= E_CTRL_MAX)
        return 1;
    ems_mode_set(E_CTRL_MANUAL);
    return 0;
}

int wrap_do_out(pcs_ctrl_var_t *var,act_func_param_t param)
{
    //param.p1 : identifer
    //param.n1 : off &  on
    if(!param.p1 )
        return 1;
    if(param.n1 != E_OFF && param.n1 != E_ON )
        return 1;
    auxi_set(var, param.p1, param.n1);
    return 0;
}

int wrap_do_set(pcs_ctrl_var_t *var,act_func_param_t param)
{
    //param.p1 : identifer
    if(!param.p1 )
        return 1;
    auxi_set(var, param.p1, E_ON);
    return 0;
}

int wrap_do_reset(pcs_ctrl_var_t *var,act_func_param_t param)
{
    //param.p1 : identifer
    if(!param.p1 )
        return 1;
    auxi_set(var, param.p1, E_OFF);
    return 0;
}

int wrap_ems_alarm(pcs_ctrl_var_t *var,act_func_param_t param)
{
    char string[1024];
    snprintf(string,sizeof(string),"protection triggered by %s",param.p1);
    report_option(var, string);
    return 0;
}

//检查DI是否闭合
int wrap_di_is_closure(pcs_ctrl_var_t *var,act_func_param_t param)
{
    if(!param.p1 )
        return 1;
    BYTE *value = param.p1;
    if(*value != 0 ) return 0;
    else return 1;
}

//检查DI是否断开
int wrap_di_is_open(pcs_ctrl_var_t *var,act_func_param_t param)
{
    if(!param.p1 )
        return 1;
    BYTE *value = param.p1;
    if(*value != 0 ) return 0;
    else return 1;
}

//重置计时器 
//TODO: 需要实现按照按照名称的KV键值对!!!!!
static time_t last = 0; //临时凑乎用
int wrap_timer_reset(pcs_ctrl_var_t *var,act_func_param_t param)
{
    if(!param.p1 )
        return 1;
    time(&last);
    return 0;
}

//检查计时器
int wrap_timer_is_timeout(pcs_ctrl_var_t *var,act_func_param_t param)
{
    if(!param.p1 )
        return 1;
    time_t now;
    time(&now);
    if(now >= (last + param.n1)) return 0;//timeout
    else return 1;
}

int wrap_ups_shutdown(pcs_ctrl_var_t *var,act_func_param_t param)
{
    return 0;
}

//仅仅支持 grid,load
int wrap_meter_timeout(pcs_ctrl_var_t *var,act_func_param_t param)
{
    if(!param.p1 )
        return 1;
    time_t now;
    time(&now);
    if(strcmp(param.p1,"grid") == 0)
        if(now >= (g_charge_mng_info.update_time.P1 + param.n1)) return 0;//timeout
    if(strcmp(param.p1,"load") == 0)
        if(now >= (g_charge_mng_info.update_time.P3 + param.n1)) return 0;//timeout    
    return 1;
}



