#include "kit_table.h"

#include "soc_calculate.h"
#include "sop_calculate.h"
#include "fault_manager.h"
#include "dido_manager.h"
#include "eeprom_manager.h"
#include "signal_manager.h"
#include "statistic_manager.h"
#include "run_status.h"

#include "table_comm.h"

typedef struct
{
    bool     is_chg_forbid;
    bool     is_dis_forbid;
    uint8_t  chg_tab_idx;
    
    uint32_t chg_forbid_dly;
    uint32_t dis_forbid_dly;
    
    uint32_t chg_forbid_dly1;
    uint32_t dis_forbid_dly1;
    uint16_t rate_data[kSopData_End];
    uint16_t sop_data[kSopData_End];
}SopItem;

SopItem sop_item;


uint16_t bms_get_sop_data(SopData idx)
{
    uint16_t tmp = 0;
    if(idx < kSopData_End)
    {
        tmp = sop_item.sop_data[idx];
    }
    return tmp;
}

typedef enum
{
    kEndChgCurStep_Normal,
    kEndChgCurStep_First,
    kEndChgCurStep_Second,
    kEndChgCurStep_Full,
    kEndChgCurStep_Forbid,
    kEndChgCurStep_End,
}EndChgCurStep;


void bms_analyse_chg_sop(uint32_t base_time)
{
    static uint16_t dly = 0;
    bool is_forbid_chg;// 充电禁止标志
    uint16_t fault_cur, end_cur, fault_power, end_power, req_volt, total_volt;
    uint16_t soc, min_temp, max_temp;
    int32_t min_temp_cur, max_temp_cur;
    
    soc = bms_get_soc() / 100;
    min_temp = (int32_t)bms_get_statistic_data(kStatisticData_MinTemp) /10 - 50;	
	max_temp = (int32_t)bms_get_statistic_data(kStatisticData_MaxTemp) /10 - 50;
	total_volt = bms_get_statistic_data(kStatisticData_TotalVolt) > 300 ? bms_get_statistic_data(kStatisticData_TotalVolt):300;//534
    
	if(get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CP)
	{	
		if((sop_item.chg_tab_idx > 0) && (sop_item.chg_tab_idx < kSopTab_End))
		{
			kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, min_temp, &min_temp_cur);	//功率表分辨率 0.1Kwh
			kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, max_temp, &max_temp_cur);		
			end_power = (min_temp_cur < max_temp_cur) ? min_temp_cur : max_temp_cur;
			end_cur = (uint32_t)end_power * 10000/total_volt; //电流分辨率0.1A
				
		}
		else
		{
			end_power = sop_item.rate_data[kSopData_ChgPower];//50
			end_cur = (uint32_t)sop_item.rate_data[kSopData_ChgPower] * 10000/total_volt;
		}
	}
	else if(get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CC)
	{
		if((sop_item.chg_tab_idx > 0) && (sop_item.chg_tab_idx < kSopTab_End))
		{
			kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, min_temp, &min_temp_cur);	
			kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, max_temp, &max_temp_cur);		
			end_cur = (min_temp_cur < max_temp_cur) ? min_temp_cur : max_temp_cur;
			end_power = (uint32_t)end_cur * total_volt/100; 
				
		}
		else
		{
			end_cur = sop_item.rate_data[kSopData_ChgCur];
			end_power = (uint32_t)end_cur * total_volt/100;
		}	
	}
	else
	{
		end_cur = 0;
		end_power = 0;
	}
			   
    req_volt = sop_item.rate_data[kSopData_ChgVolt];

    fault_cur = 0;
    fault_power = 0;
    is_forbid_chg = false;
    //故障降流
    if((bms_is_chg_allow() == false)
    || (bms_get_circuit_status(kCircuitType_Chg) == kCircuitStatus_Off))
    {
        if(bms_is_single_full_chg() == true)
        {
            //有故障任要发送禁充指令
            if(bms_is_chg_circuit_allow() == false)
            {
                is_forbid_chg = true;
            }
        }
        else
        {
            is_forbid_chg = true;
        }
    }
    else if(bms_get_soc_status() == kSocStatus_Full)
    {
        //满充再单簇校准模式下不上发禁充
        if(bms_is_single_full_chg() == false)
        {
            is_forbid_chg = true;
        }
    }
    else 
    {
        fault_cur = (uint32_t)end_cur * bms_get_fault_cur_rate(kRunStatus_Chg) / 100;
		fault_power = (uint32_t)end_power * bms_get_fault_cur_rate(kRunStatus_Chg) / 100;
    }
    //末端单体电压降流
    if(bms_get_signal(kSignalIdx_Chg2ndCurDown) == kSignalStatus_High)
    {
        end_cur = (uint32_t)end_cur * get_eeprom_data(kEep_ChgSnd_FstCurDownRate, kEepromDataType_High) / 100;
		end_power = (uint32_t)end_power * get_eeprom_data(kEep_ChgSnd_FstCurDownRate, kEepromDataType_High) / 100;
    }
    else if(bms_get_signal(kSignalIdx_Chg1stCurDown) == kSignalStatus_High)
    {
        end_cur = (uint32_t)end_cur * get_eeprom_data(kEep_ChgSnd_FstCurDownRate, kEepromDataType_Low) / 100;
		end_power = (uint32_t)end_power * get_eeprom_data(kEep_ChgSnd_FstCurDownRate, kEepromDataType_Low) / 100;
    }


    if(fault_cur > end_cur)
    {
        fault_cur = end_cur;
    }
	
	if(fault_power > end_power)
    {
        fault_power = end_power;
    }

    sop_item.sop_data[kSopData_ChgCur] = fault_cur;
	sop_item.sop_data[kSopData_ChgPower] = fault_power;
    
    
    if((fault_cur == 0) && (is_forbid_chg == true))
    {        
        dly += base_time;
        if(dly >= 500)
        {
            dly = 500;
            if(bms_get_fault_cur_rate(kRunStatus_Chg) != 0)
            {
               sop_item.chg_forbid_dly = get_eeprom_data(kEep_ForbidChgRelDelay, kEepromDataType_Full) * 6000; 
            }
              
            sop_item.chg_forbid_dly1 = 0;
            sop_item.is_chg_forbid = true;
            bms_set_signal(kSignalIdx_ForbidChg, kSignalStatus_High);
        }
    }
    else
    {
        dly = 0;
    }
    if(sop_item.is_chg_forbid == true)
    {
        sop_item.chg_forbid_dly += base_time;
        sop_item.chg_forbid_dly1 += base_time;
        sop_item.sop_data[kSopData_ChgCur] = sop_item.sop_data[kSopData_ChgPower] = 0;
        if((sop_item.chg_forbid_dly1 >= 2000) && (sop_item.chg_forbid_dly >= get_eeprom_data(kEep_ForbidChgRelDelay, kEepromDataType_Full) * 6000))
        {
            sop_item.is_chg_forbid = false;
            sop_item.chg_forbid_dly1 = 2000;
            sop_item.chg_forbid_dly = get_eeprom_data(kEep_ForbidChgRelDelay, kEepromDataType_Full) * 6000;
            bms_set_signal(kSignalIdx_ForbidChg, kSignalStatus_Low);
        }
    }
    
    sop_item.sop_data[kSopData_ChgVolt] = req_volt;
}

void bms_set_dis_forbid_status(void)
{
    sop_item.dis_forbid_dly = 0;
    sop_item.is_dis_forbid = true;
    bms_set_signal(kSignalIdx_ForbidDis, kSignalStatus_High);
}

void bms_set_chg_forbid_status(void)
{
    sop_item.chg_forbid_dly = 0;
    sop_item.is_chg_forbid = true;
    bms_set_signal(kSignalIdx_ForbidChg, kSignalStatus_High);
}

void bms_analyse_dis_sop(uint32_t base_time)
{
    static uint16_t dly;
    uint16_t fault_cur, end_cur, fault_power, end_power,total_volt;
	total_volt = bms_get_statistic_data(kStatisticData_TotalVolt) > 500 ? bms_get_statistic_data(kStatisticData_TotalVolt):500;
	
	if(get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CP)
	{
		end_power = fault_power = sop_item.rate_data[kSopData_DisPower];
		end_cur = fault_cur = (uint32_t)sop_item.rate_data[kSopData_DisPower] * 10000 /total_volt;
	}
	else if(get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CC)
	{
		end_power = fault_power = (uint32_t)sop_item.rate_data[kSopData_DisCur]  * total_volt /100;
		end_cur = fault_cur = sop_item.rate_data[kSopData_DisCur];
	}
	else
	{
		end_power = 0;
		end_cur = 0;
	}
    //故障降流
    if((bms_is_dis_allow() == false) 
    || (bms_get_soc_status() == kSocStatus_Empty)
    || (bms_get_circuit_status(kCircuitType_Dis) == kCircuitStatus_Off) )
    {
        fault_cur = 0;
		fault_power = 0;
    }
    else
    {
        fault_cur = (uint32_t)fault_cur * bms_get_fault_cur_rate(kRunStatus_Dis) / 100;
		fault_power = (uint32_t)fault_power * bms_get_fault_cur_rate(kRunStatus_Dis) / 100;
    }

    if(fault_cur > end_cur)
    {
        fault_cur = end_cur;
    }
	
    if(fault_power > end_power)
    {
        fault_power = end_power;
    }
    sop_item.sop_data[kSopData_DisCur] = fault_cur;
	sop_item.sop_data[kSopData_DisPower] = fault_power;
    
    
    if(fault_cur == 0)
    {
        dly += base_time;
        if(dly >= 500)
        {
             dly = 500;
            if(bms_get_fault_cur_rate(kRunStatus_Dis) != 0)
            {
               sop_item.dis_forbid_dly = get_eeprom_data(kEep_ForbidDisRelDelay, kEepromDataType_Full) * 6000; 
            }            
            sop_item.dis_forbid_dly1 = 0;
            sop_item.is_dis_forbid = true;
            bms_set_signal(kSignalIdx_ForbidDis, kSignalStatus_High);
        }
    }
    else
    {
        dly = 0;
    }
    
    if(sop_item.is_dis_forbid == true)
    {
        sop_item.dis_forbid_dly += base_time;
        sop_item.dis_forbid_dly1 += base_time;
        sop_item.sop_data[kSopData_DisCur] = sop_item.sop_data[kSopData_DisPower] = 0;
        if((sop_item.dis_forbid_dly1 >= 2000) 
        && (sop_item.dis_forbid_dly >= get_eeprom_data(kEep_ForbidDisRelDelay, kEepromDataType_Full) * 6000))
        {
            sop_item.is_dis_forbid = false;
            sop_item.dis_forbid_dly1 = 2000;
            sop_item.dis_forbid_dly = get_eeprom_data(kEep_ForbidDisRelDelay, kEepromDataType_Full) * 6000;
            bms_set_signal(kSignalIdx_ForbidDis, kSignalStatus_Low);
        }
    }
    
}


void bms_poll_sop(uint32_t base_time)
{
    bms_analyse_dis_sop(base_time);
	bms_analyse_chg_sop(base_time);
}


void bms_init_sop(void)
{
    sop_item.chg_tab_idx = get_eeprom_data(kEep_Sop_OcvIndex, kEepromDataType_High);
	if(get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CP)
	{
		sop_item.rate_data[kSopData_DisPower] = get_eeprom_data(kEep_RatedDisPower, kEepromDataType_Full);
		sop_item.rate_data[kSopData_ChgPower] = get_eeprom_data(kEep_RatedChgPower, kEepromDataType_Full);		
	}
	else if(get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CC)
	{
		sop_item.rate_data[kSopData_DisCur] = get_eeprom_data(kEep_RatedDisCur, kEepromDataType_Full);
		sop_item.rate_data[kSopData_ChgCur] = get_eeprom_data(kEep_RatedChgCur, kEepromDataType_Full);
	}
	else
	{
		;
	}
	sop_item.rate_data[kSopData_ChgVolt] = get_eeprom_data(kEep_ReqCghVolt, kEepromDataType_Full);
}

