#include "drv_rtc.h"
#include "drv_gpio.h"

#include "iso_check.h"
#include "version_manager.h"
#include "gpio_manager.h"
#include "dido_manager.h"
#include "fault_manager.h"
#include "hv_adc_manager.h"
#include "eeprom_manager.h"
#include "signal_manager.h"
#include "run_status.h"

#include "logic_ctrl.h"


typedef struct
{
    bool      is_single_full_chg;
    uint8_t   bus_bar_bcu;
    RunCtrl   run_ctrl;
    RunStatus run_status;
    RunStatus run_ctrl_status;
    uint16_t  cmd_heart_beat;
    CircuitStatus circuit_st[kCircuitType_End];
    CircuitStatus circuit_cmd_st;

}RunItem;

RunItem run_item;

RunStatus bms_get_run_status(void)
{
	return run_item.run_status;
}

//获得充放电模式指令
RunStatus bms_get_run_ctrl_status(void)
{
	return run_item.run_ctrl_status;
}

//下发充放电模式指令
void bms_set_run_ctrl_status(RunStatus status)
{
	run_item.run_ctrl_status = status;
}


uint8_t bms_get_bus_bar_bcu(void)
{
	return run_item.bus_bar_bcu;
}

void bms_set_bus_bar_bcu(uint8_t idx)
{
	run_item.bus_bar_bcu = idx;
}

bool bms_is_bus_bar_bcu(void)
{
	return (run_item.bus_bar_bcu == bms_get_tag_data(kTagData_DevAddr));
}

void bms_clear_cmd_heartbeat(void)
{
    run_item.cmd_heart_beat = 0;
}

uint16_t bms_get_cmd_heartbeat(void)
{
    return run_item.cmd_heart_beat;
}

bool bms_is_single_full_chg(void)
{
    return run_item.is_single_full_chg;
}

void bms_set_single_full_chg_status(bool is_en)
{
    run_item.is_single_full_chg = is_en;
}

void bms_set_circuit_status(CircuitType type, CircuitStatus st)
{
    if(type < kCircuitType_End)
    {
        run_item.circuit_st[type] = st;
    }
}

CircuitStatus bms_get_circuit_status(CircuitType type)
{
    CircuitStatus st = kCircuitStatus_Off;
    
    if(type < kCircuitType_End)
    {
        st = run_item.circuit_st[type];
    }
	return st;
}

void bms_set_circuit_cmd_status(CircuitStatus st)
{
    run_item.cmd_heart_beat = 0;
    if(run_item.run_ctrl == kRunCtrl_Cmd)
    {
        run_item.circuit_cmd_st = st;
    }
}

CircuitStatus bms_get_circuit_cmd_status(void)
{
    return run_item.circuit_cmd_st;
}

bool bms_is_dis_circuit_allow(void)
{
    bool res = true;
    
    //允许放电的工作状态,异回路：放电状态;同回路+UPS：非初始化状态(充电、放电、待机)
    res = (bms_get_main_ctrl_strategy() == kDoCtrlStrategy_DiffCircuit) ? (run_item.run_status == kRunStatus_Dis) : (run_item.run_status != kRunStatus_Init);
    if((res != true) || (bms_get_fault_relay_off_bit_by_status(kRunStatus_Dis) != 0)
			|| (bms_get_signal(kSignalIdx_LowVoltSleep) == kSignalStatus_High)|| (bms_get_signal(kSignalIdx_StandbySleep) == kSignalStatus_High))
//    || ((bms_get_signal(kSignalIdx_ForbidDis) == kSignalStatus_High) && (run_item.run_status != kRunStatus_Chg))) 
    {
        res = false;
    }
    return res;
}

bool bms_is_dis_allow(void)
{
    bool res = true;
    if((bms_is_dis_circuit_allow() == false)
    || (run_item.circuit_cmd_st == kCircuitStatus_Off))
    {
        res = false;
    }
    return res;
}

bool bms_is_chg_circuit_allow(void)
{
    bool res = true;
    
    //允许充电的工作状态,异回路：充电状态;同回路+UPS：非初始化状态(充电、放电、待机)
    res = (bms_get_main_ctrl_strategy() == kDoCtrlStrategy_DiffCircuit) ? (run_item.run_status == kRunStatus_Chg) : (run_item.run_status != kRunStatus_Init);
    if((res != true) || (bms_get_fault_relay_off_bit_by_status(kRunStatus_Chg) != 0)
     	|| (bms_get_signal(kSignalIdx_LowVoltSleep) == kSignalStatus_High)|| (bms_get_signal(kSignalIdx_StandbySleep) == kSignalStatus_High))
		{
        res = false;
    }
    return res;
}


bool bms_is_chg_allow(void)
{
    bool res = true;
    if((bms_is_chg_circuit_allow() == false)
    || (run_item.circuit_cmd_st == kCircuitStatus_Off))
    {
        res = false;
    }
    return res;
}

bool bms_is_circuit_allow(void)
{
    bool res;
    if(bms_get_main_ctrl_strategy() == kDoCtrlStrategy_SameCircuit)
    {
        res = bms_is_chg_circuit_allow() && bms_is_dis_circuit_allow();
    }
    else
    {
        res = bms_is_chg_circuit_allow() || bms_is_dis_circuit_allow();
    }
    
    return res;
}


RunStatus bms_analyse_run_status(void)
{
    RunStatus run_status = kRunStatus_Standby;
    RunStatusBasis basis = (RunStatusBasis)get_eeprom_data(kEep_ChgDisChangeBasis_RelayOnOffMode, kEepromDataType_High);

    switch(basis)
	{
		case kRunStatusBasis_Cur:
			if(bms_get_signal(kSignalIdx_ChgCur) == kSignalStatus_High)
            {
                run_status = kRunStatus_Chg;
            }
            else if(bms_get_signal(kSignalIdx_DisCur) == kSignalStatus_High)
            {
                run_status = kRunStatus_Dis;
            }
			break;
		case kRunStatusBasis_Cmd:
			if(run_item.run_ctrl_status == kRunStatus_Chg)
            {
				run_status = kRunStatus_Chg;
            }
            else if(run_item.run_ctrl_status == kRunStatus_Dis)
            {
				run_status = kRunStatus_Dis;
            }
			break;
		case kRunStatusBasis_CC2:
			if(bms_get_signal(kSignalIdx_CC2) == kSignalStatus_High)
            {
				run_status = kRunStatus_Chg;
            }
            else
            {
				run_status = kRunStatus_Dis;
            }
			break;
		default:
			break;
	}
    
    return run_status;
}


void bms_poll_run_status(uint32_t base_time)
{
	RunStatus cur_run_status = bms_analyse_run_status();
    bms_update_fault_data(base_time);
    
    if((run_item.run_ctrl != kRunCtrl_Self) && (run_item.cmd_heart_beat < 65000))
    {
        run_item.cmd_heart_beat += base_time;
    }
	switch (run_item.run_status)
	{		
		case kRunStatus_Init:            
			bms_check_pwr_on_fault(base_time);
            run_item.run_status = kRunStatus_Standby;
			break;
		
		case kRunStatus_Chg:
			bms_check_chg_run_fault(kRunStatus_Chg, base_time);
            if(cur_run_status == kRunStatus_Dis)
			{
				bms_clear_fault_code(kRunStatus_Chg);
				run_item.run_status = kRunStatus_Dis;
			}  
			else if(cur_run_status == kRunStatus_Standby)
			{
				run_item.run_status = kRunStatus_Standby;
			}			
			break;
		
		case kRunStatus_Dis:
			bms_check_dis_run_fault(kRunStatus_Dis, base_time);
            if(cur_run_status == kRunStatus_Chg)
			{
				bms_clear_fault_code(kRunStatus_Dis);
				run_item.run_status = kRunStatus_Chg;
			} 
			else if(cur_run_status == kRunStatus_Standby)
			{
				run_item.run_status = kRunStatus_Standby;
			}
			break;
		case kRunStatus_Standby:
			bms_check_dis_run_fault(kRunStatus_Dis, base_time);
			bms_check_chg_run_fault(kRunStatus_Chg, base_time);
			if(cur_run_status == kRunStatus_Chg)
			{
				bms_clear_fault_code(kRunStatus_Dis);// 进入充电状态，清除放电故障
				run_item.run_status = kRunStatus_Chg;
			}
			else if(cur_run_status == kRunStatus_Dis)
			{
				bms_clear_fault_code(kRunStatus_Chg);// 进入放电状态，清除充电故障
				run_item.run_status = kRunStatus_Dis;
			}
			break;
			
		case kRunStatus_PwrOff:
			
			break;
        
        case kRunStatus_Stop:
            
			break;
		
		default:
			run_item.run_status = kRunStatus_PwrOff;
			break;
	}
}

void bms_init_run(void)
{
    run_item.bus_bar_bcu = 0xFF;
    run_item.run_status = kRunStatus_Init;
    run_item.run_ctrl = (RunCtrl)get_eeprom_data(kEep_ChgDisChangeBasis_RelayOnOffMode, kEepromDataType_Low);
    if(run_item.run_ctrl == kRunCtrl_Self)
    {
        bms_set_iso_bsu_ctrl(kIsoCtrl_Enable);
        run_item.circuit_cmd_st = kCircuitStatus_On;
        run_item.bus_bar_bcu = get_eeprom_data(kEep_DevAddr_SlaverNum, kEepromDataType_High);
    }
}
