#include "../adapter/pe_adapter.h"
#include <string.h>
#include "../common.h"

#define TYPE_INPOWER 0
#define TYPE_INPOWER_3P4W 1
#define TYPE_INPOWER_X3 2
#define TYPE_INPOWER_X4 3

#define NQ_ZERO(d) (((d) > 0.001) || ((d) < -0.001))
static int inpower_pcs_set_onoff(pe_class *this_p, int onoff);
static int inpower_pcs_get_onoff(pe_class *this_p, int *onoff);

static int inpower_set_power_check_status(pe_class *this_p)
{
    int tmp = 0;
    tmp = dev_get_dev_tag_int(this_p->no, "ControlMode");
    if (tmp == 0) // 就地模式
    {
        dev_set_dev_tag_int(this_p->no, "SetRemoteLocal", 1); // 设置为远程模式
    }

    inpower_pcs_get_onoff(this_p, &tmp);
    if (tmp == 0)
    {
        inpower_pcs_set_onoff(this_p, PE_ADP_ON);
    }

    return 0;
}

int inpower_pcs_init(pe_class *this_p, void *par)
{
    return 0;
}

int inpower_pcs_set_power(pe_class *this_p, double power)
{
    if (NQ_ZERO(power))
    {
        inpower_set_power_check_status(this_p);
    }
    switch (this_p->compatible_index)
    {
    case TYPE_INPOWER:
    case TYPE_INPOWER_X4:
        power = power / 3.0;
        dev_set_dev_tag_float(this_p->no, "ASplitPhaseActPowSet", power);
        dev_set_dev_tag_float(this_p->no, "BSplitPhaseActPowSet", power);
        dev_set_dev_tag_float(this_p->no, "CSplitPhaseActPowSet", power);
        break;

    case TYPE_INPOWER_3P4W:
    case TYPE_INPOWER_X3:
        dev_set_dev_tag_float(this_p->no, "ActPowSet", power);
        break;

    default:
        ems_syslog(LOG_NOTICE, "inpower pcs  compatible id error:%d", this_p->compatible_index);
        break;
    }
    ems_syslog(LOG_NOTICE, "inpower_pcs_set_power %f", power);
    return 0;
}

int inpower_pcs_set_repower(pe_class *this_p, double repower)
{

    if (NQ_ZERO(repower))
    {
        inpower_set_power_check_status(this_p);
    }
    switch (this_p->compatible_index)
    {
    case TYPE_INPOWER:
    case TYPE_INPOWER_X4:
        repower = repower / 3.0;
        dev_set_dev_tag_float(this_p->no, "ASplitPhaseReactPowSet", repower);
        dev_set_dev_tag_float(this_p->no, "BSplitPhaseReactPowSet", repower);
        dev_set_dev_tag_float(this_p->no, "CSplitPhaseReactPowSet", repower);
        break;

    case TYPE_INPOWER_3P4W:
    case TYPE_INPOWER_X3:
        dev_set_dev_tag_float(this_p->no, "ReactPowSet", repower);
        break;

    default:
        ems_syslog(LOG_NOTICE, "inpower pcs  compatible id error:%d", this_p->compatible_index);
        break;
    }

    ems_syslog(LOG_NOTICE, "inpower_pcs_set_repower %f", repower);
    return 0;
}

int inpower_pcs_set_mode(pe_class *this_p, int mode)
{
    return 0;
}
int inpower_pcs_set_onoff(pe_class *this_p, int onoff)
{
    int re = -1;
    ems_syslog(LOG_NOTICE, "inpower_pcs_set_onoff %d", onoff);
    if (onoff == PE_ADP_ON)
    {
        dev_set_dev_tag_int(this_p->no, "FaultRun", 1);
        re = 0;
    }
    else if (onoff == PE_ADP_OFF)
    {
        dev_set_dev_tag_int(this_p->no, "FaultStop", 1);
        re = 0;
    }
    return re;
}
int inpower_pcs_set_connect(pe_class *this_p, int connect)
{
    if (connect == PE_ADP_CONNECT_GRID)
    {
        dev_set_dev_tag_int(this_p->no, "SetGridModel", 0);
    }
    else if (connect == PE_ADP_DISCONNECT_GRID)
    {
        dev_set_dev_tag_int(this_p->no, "SetGridModel", 1);
    }
    else
    {
        return -1;
    }
    return 0;
}

int inpower_pcs_get_power(pe_class *this_p, double *power)
{
    *power = dev_get_dev_tag_float(this_p->no, "ActivePower");
    return 0;
}

int inpower_pcs_get_repower(pe_class *this_p, double *power)
{
    *power = dev_get_dev_tag_float(this_p->no, "ReactivePower");
    return 0;
}

int inpower_pcs_get_mode(pe_class *this_p, int *mode)
{
    return 0;
}
int inpower_pcs_get_onoff(pe_class *this_p, int *onoff)
{
    if (0 != dev_get_dev_tag_int(this_p->no, "RunStatu"))
    {
        *onoff = PE_ADP_ON;
    }
    else if (0 != dev_get_dev_tag_int(this_p->no, "Stoppage"))
    {
        *onoff = PE_ADP_OFF;
    }
    else
    {
        *onoff = PE_ADP_STANDBY;
    }
    return 0;
}
int inpower_pcs_get_connect(pe_class *this_p, int *connect)
{
    return 0;
}

int inpower_pcs_set_value(pe_class* this_p, const char* function, double value)
{
    if (strcmp(function, FUNCTION_SET_POWER) == 0)
    {
        return inpower_pcs_set_power(this_p, value);
    }
    else if (strcmp(function, FUNCTION_SET_REPOWER) == 0)
    {
        return inpower_pcs_set_repower(this_p, value);
    }
    else if (strcmp(function, FUNCTION_SET_MODE) == 0)
    {
        return inpower_pcs_set_mode(this_p, (int)value);
    }
    else if (strcmp(function, FUNCTION_SET_ONOFF) == 0)
    {
        return inpower_pcs_set_onoff(this_p, (int)value);
    }
    else if (strcmp(function, FUNCTION_SET_CONNECT) == 0)
    {
        return inpower_pcs_set_connect(this_p, (int)value);
    }
    else
    {
        return adapter_function_set(this_p, function, value);
    }
    return -1;
}

int inpower_pcs_get_int_value(pe_class* this_p, const char* function, int* value)
{
    if (strcmp(function, FUNCTION_GET_ONOFF) == 0)
    {
        return inpower_pcs_get_onoff(this_p, value);
    }
    else if (strcmp(function, FUNCTION_GET_MODE) == 0)
    {
        return inpower_pcs_get_onoff(this_p, value);
    }
    else if (strcmp(function, FUNCTION_GET_CONNECT) == 0)
    {
        return inpower_pcs_get_onoff(this_p, value);
    }
    else
    {
        return adapter_function_get_int(this_p, function, value);
    }
    return -1;
}

int inpower_pcs_get_double_value(pe_class* this_p, const char* function, double* value)
{
    if (strcmp(function, FUNCTION_GET_POWER) == 0)
    {
        return inpower_pcs_get_power(this_p, value);
    }
    else if (strcmp(function, FUNCTION_GET_REPOWER) == 0)
    {
        return inpower_pcs_get_repower(this_p, value);
    }
    else
    {
        return adapter_function_get_double(this_p, function, value);
    }
    return -1;
}

static char *inpower_pcs_compatible_arr[] = {"inpower", "inpower-3p4w", "inpower_x3", "inpower_x4", NULL};

pe_adapter inpower_pcs_adp __at_pe_adp_section = {
    .compatible = inpower_pcs_compatible_arr, // 属性
    //
    .init = inpower_pcs_init,
    //
    .set_power = inpower_pcs_set_power,
    .set_repower = inpower_pcs_set_repower,
    .set_mode = inpower_pcs_set_mode,
    .set_onoff = inpower_pcs_set_onoff,
    .set_connect = inpower_pcs_set_connect,
    //
    .get_power = inpower_pcs_get_power,
    .get_repower = inpower_pcs_get_repower,
    .get_mode = inpower_pcs_get_mode,
    .get_onoff = inpower_pcs_get_onoff,
    .get_connect = inpower_pcs_get_connect,

    .set_value        = inpower_pcs_set_value,
    .get_int_value    = inpower_pcs_get_int_value,
    .get_double_value = inpower_pcs_get_double_value,
};
