#include "bmser_can_j1939_syn_data.h"
#include "j1939_map_db_obj_cfg.h"
#include "bmser_project_para.h"
#include "bmser_can_j1939_send.h"
#include "bcu_db_addr.h"
#include "bmser_db_control_db.h"
#include "xieneng_can_component.h"

Syn_Sample_Data_Master_Stru *g_pSynSampleDataMaster = NULL;
static int g_RackNum = 0;                               /*簇数量*/
uint16_t g_IsEnableSendQueryRequest = Std_False;        /*请求单体信息标志*/

#define SYN_SAMPLE_DATA_MASTER_QUERY_PERIOD     100     /*同步采样查询周期，单位10ms*/
#define SYN_SAMPLE_DATA_MASTER_SYNCH_PERIOD     6000    /*同步采样Tick周期，单位10ms*/
#define SYN_SAMPLE_DATA_MASTER_QUERY_WAIT_CNT   1       /*等待查询完成最大次数*/
#define SYN_SAMPLE_DATA_MASTER_RESPONSE_ERR     500     /*主控响应采样tick差值错误的范围，单位1ms*/
#define SYN_SAMPLE_DATA_MASTER_SAMPLE_TICK_ERR  100     /*主控响应采样tick差值过大的范围，单位1ms*/


/*！！！下列宏不建议更改！！！*/
#define SYN_SAMPLE_DATA_MASTER_SAMPLE_TRANSITON_TIME    15  /*采样转换时间，单位10ms*/
#define SYN_SAMPLE_DATA_MASTER_ADVANCE_JUDGE            6   /*提前时间：告诉主控上一秒的同步数据收齐，单位10ms*/


 typedef enum
 {
     Synch_State_Send_SynTick,
     Synch_State_Send_QueryTick,
     Synch_State_Wait_Query_Info,
 }Synch_State_Enum;

/*!
 * @brief       获取请求单体信息的标志
 *
 * @param[in]   void
 * @return
 * @retval      g_IsEnableSendQueryRequest
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-08-24    qzy       Create             \n
 *
 */
uint16_t get_IsEnableSendQueryRequest(void)
{
    return g_IsEnableSendQueryRequest;
}

/*!
 * @brief       发送同步帧
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-05-8    zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_StateSwitch(Synch_State_Enum state)
{
    if(g_pSynSampleDataMaster == NULL)
    {
        return Std_Ret_ERR;
    }

    g_pSynSampleDataMaster->state = state;
    g_pSynSampleDataMaster->sendFlag = (uint16_t)Std_False;
    g_pSynSampleDataMaster->waitRespCnt = 0;

    if(state == Synch_State_Wait_Query_Info)
    {
        g_IsEnableSendQueryRequest = Std_True;
        g_pSynSampleDataMaster->allowSdRecodeFlag = (uint16_t)Std_True;
        // 以projet_para中配置的簇数为准
        memset(g_pSynSampleDataMaster->queryRevFlag,0x00,(g_RackNum * 2));
    }
    else
    {
        g_IsEnableSendQueryRequest = Std_False;
    }
    return Std_Ret_OK;
}


/*!
 * @brief       同步采样信号回调
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-04-14   zzk       Create             \n
 * 2023-08-11   zzk       增加同步信息unix时间戳记录\n
 * 2023-08-16   zzk       修复单体电池的数量\n
 */
Std_Ret_Type SynSampleDataMaster_Callback(uint16_t *data,uint32_t length, uint8_t bcuIndex, uint16_t bankId, uint16_t rackId)
{
    int16_t i = 0;
    uint16_t crc = 0, dataCrc = 0;
    uint16_t batNum = 0;

    if(g_pSynSampleDataMaster == NULL)
    {
        return Std_Ret_ERR;
    }

    if(length == 0 || length < (SYNCHRO_BATVOL + 1))
    {
        return Std_Ret_ERR;
    }
    data[SYNCHRO_TAG]  = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_TAG]);
    data[SYNCHRO_RES1] = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_RES1]);
    data[SYNCHRO_RES2] = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_RES2]);
    data[SYNCHRO_RES3] = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_RES3]);
    data[SYNCHRO_RES4] = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_RES4]);
    data[SYNCHRO_TICK] = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_TICK]);
    data[SYNCHRO_UNIX_EPOCH_H]  = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_UNIX_EPOCH_H]);
    data[SYNCHRO_UNIX_EPOCH_L]  = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_UNIX_EPOCH_L]);
    data[SYNCHRO_TORALVOL]      = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_TORALVOL]);
    data[SYNCHRO_CURRENTL]      = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_CURRENTL]);
    data[SYNCHRO_AVE_CURRENT]   = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_AVE_CURRENT]);
    for(i = 0; i < (length - SYNCHRO_BATVOL - 1); i++)  /*最后一个字节CRC*/
    {
        data[SYNCHRO_BATVOL + i] = LITTLE_ENDIAN_TO_HOST_16(data[SYNCHRO_BATVOL + i]);
    }

    dataCrc = LITTLE_ENDIAN_TO_HOST_16(data[length-1]);
    crc = CalculateU16XorCrc((uint8_t *)&data[SYNCHRO_TAG], (length-1) * 2);
    if(crc != dataCrc)
    {
        g_pSynSampleDataMaster->crcErrorCnt++;
        return Std_Ret_ERR;
    }

    g_pSynSampleDataMaster->unixEpoch[bcuIndex] = ((uint32_t)data[SYNCHRO_UNIX_EPOCH_H]<<16) | data[SYNCHRO_UNIX_EPOCH_L];
    g_pSynSampleDataMaster->synTotalVolt[bcuIndex] = data[SYNCHRO_TORALVOL];
    g_pSynSampleDataMaster->aveCurrent[bcuIndex] = data[SYNCHRO_AVE_CURRENT];
    g_pSynSampleDataMaster->synCurrent[bcuIndex] = data[SYNCHRO_CURRENTL];
    g_pSynSampleDataMaster->synTick[bcuIndex] = data[SYNCHRO_TICK];

    batNum = MIN((length - SYNCHRO_BATVOL - 1), MAX_BATTERY_NUM_IN_ONE_CLUSTER);

    // 写入单体电压详细信息
    EMS_DEV_REG_DATA_S regData = {0};
    regData.bankId = bankId;
    regData.rackId = rackId;
    regData.regCount = batNum;
    regData.len = (unsigned short)length;
    convertArrayToLittleEndian(&data[SYNCHRO_BATVOL], regData.len);
    regData.data = (uint8_t*)&data[SYNCHRO_BATVOL];
    regData.startAddr = BMS_VOLTAGE_SUBOBJ_ID_1;
    BmserProtocolExt_UpdateRegisterDb(&regData);

    g_pSynSampleDataMaster->queryRevFlag[bcuIndex] = (uint16_t)Std_True;
    
    return Std_Ret_OK;
}

/*!
 * @brief       发送同步帧状态
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-05-8    zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_SendSynchFrame(void)
{
    if(g_pSynSampleDataMaster == NULL)
    {
        return Std_Ret_ERR;
    }
    
    if(g_pSynSampleDataMaster->sendFlag == (uint16_t)Std_True)
    {
        if(g_pSynSampleDataMaster->innerCount >= (SYN_SAMPLE_DATA_MASTER_QUERY_PERIOD - SYN_SAMPLE_DATA_MASTER_ADVANCE_JUDGE))
        {
            SynSampleDataMaster_StateSwitch(Synch_State_Send_QueryTick);
        }
    }
    else
    {
        g_pSynSampleDataMaster->sendFlag = (uint16_t)Std_True;
        g_pSynSampleDataMaster->lastSynchSysTick = get_tick_count();
        HubMainDbJ1939_SendClusterMsgWithoutRespCheck(J1939_BROADCAST_DST_ADDR, \
            FUNC_CODE_WRITE, BMS_FORCE_SYN_TICK, 0);
    }
    
    return Std_Ret_OK;
}
  
/*!
 * @brief       发送查询完成标志帧
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-05-8    zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_SendQueryFrame(void)
{
    if(g_pSynSampleDataMaster == NULL)
    {
        return Std_Ret_ERR;
    }

    if(g_pSynSampleDataMaster->sendFlag == (uint16_t)Std_True)
    {
        if((g_pSynSampleDataMaster->innerCount % SYN_SAMPLE_DATA_MASTER_QUERY_PERIOD) >= SYN_SAMPLE_DATA_MASTER_SAMPLE_TRANSITON_TIME)
        {
            SynSampleDataMaster_StateSwitch(Synch_State_Wait_Query_Info);
        }
    }
    else
    {
        g_pSynSampleDataMaster->sendFlag = (uint16_t)Std_True;
        HubMainDbJ1939_SendClusterMsgWithoutRespCheck(J1939_BROADCAST_DST_ADDR, \
            FUNC_CODE_WRITE, BMS_FORCE_QUERY_FINASH_FALG, g_pSynSampleDataMaster->innerCount *10);
    }
    
    return Std_Ret_OK;
}


/*!
 * @brief       等待查询恢复帧收齐状态
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-05-8    zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_WaitQueryResponse(void)
{
    int16_t rackIndex = 0;
    uint16_t maxSampleTick = 0, minSampleTick = 0xFFFF;
    int32_t revAll = Std_True;
    
    if(g_pSynSampleDataMaster == NULL)
    {
        return Std_Ret_ERR;
    }

    for(rackIndex = 0; rackIndex < g_RackNum; rackIndex++)
    {
        if(g_pSynSampleDataMaster->queryRevFlag[rackIndex] == Std_False)
        {
            revAll = Std_False;
        }
        else
        {
            if(maxSampleTick < g_pSynSampleDataMaster->synTick[rackIndex])
            {
                maxSampleTick = g_pSynSampleDataMaster->synTick[rackIndex];
            }
            if(minSampleTick > g_pSynSampleDataMaster->synTick[rackIndex])
            {
                minSampleTick = g_pSynSampleDataMaster->synTick[rackIndex];
            }
        }
    }
    
    if(g_pSynSampleDataMaster->innerCount >= SYN_SAMPLE_DATA_MASTER_SYNCH_PERIOD)
    {
        SynSampleDataMaster_StateSwitch(Synch_State_Send_SynTick);
    }
    else
    {
        if(g_pSynSampleDataMaster->innerCount % SYN_SAMPLE_DATA_MASTER_QUERY_PERIOD == (SYN_SAMPLE_DATA_MASTER_QUERY_PERIOD - SYN_SAMPLE_DATA_MASTER_ADVANCE_JUDGE))
        {
            if(revAll == Std_True)
            {
                if(maxSampleTick - minSampleTick > SYN_SAMPLE_DATA_MASTER_RESPONSE_ERR)
                {
                    g_pSynSampleDataMaster->sampleResErrorCnt++;
                }
                else if(maxSampleTick - minSampleTick > SYN_SAMPLE_DATA_MASTER_SAMPLE_TICK_ERR)
                {
                    g_pSynSampleDataMaster->tickDiffErrCnt++;
                }
                else{}
                SynSampleDataMaster_StateSwitch(Synch_State_Send_QueryTick);
            }
            else
            {
                if(g_pSynSampleDataMaster->waitRespCnt >= SYN_SAMPLE_DATA_MASTER_QUERY_WAIT_CNT)
                {
                    g_pSynSampleDataMaster->tickErrorCnt++;
                    SynSampleDataMaster_StateSwitch(Synch_State_Send_QueryTick);
                }
                else
                {
                    g_pSynSampleDataMaster->tickLongCnt++;
                    g_pSynSampleDataMaster->waitRespCnt++;
                }
            }
        }
    }

    return Std_Ret_OK;
}


 /*!
 * @brief       同步采样信息Init
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-04-14   zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_Init(void)
{
    uint32_t ret = Std_Ret_OK;

    if(g_pSynSampleDataMaster == NULL)
    {
        g_pSynSampleDataMaster = (Syn_Sample_Data_Master_Stru *)malloc(sizeof(Syn_Sample_Data_Master_Stru));
    }
    
    if(g_pSynSampleDataMaster != NULL)
    {
        memset(g_pSynSampleDataMaster,0x00,sizeof(Syn_Sample_Data_Master_Stru));
        g_pSynSampleDataMaster->state = Synch_State_Send_SynTick;
        //获取簇数
        g_RackNum = bmser_jsonGetRackNum();
    }
    else
    {
        ret = Std_Ret_ERR;
    }
    
    return ret;
}

/*!
 * @brief       同步采样信息Rnnable,周期10ms
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-04-14   zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_Runnable(void)
{
    if(g_pSynSampleDataMaster == NULL)
    {
        return Std_Ret_ERR;
    }

    g_pSynSampleDataMaster->innerCount = (uint16_t)((get_tick_count() - g_pSynSampleDataMaster->lastSynchSysTick) / 10);
    switch(g_pSynSampleDataMaster->state)
    {
        case Synch_State_Send_SynTick:
        {
            SynSampleDataMaster_SendSynchFrame();
            break;
        }
        case Synch_State_Send_QueryTick:
        {
            SynSampleDataMaster_SendQueryFrame();
            break;
        }
        case Synch_State_Wait_Query_Info:
        {
            SynSampleDataMaster_WaitQueryResponse();
            break;
        }
        default:
            break;
    }

    return Std_Ret_OK;
}


/*!
 * @brief       获取SD卡记录标志
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-04-14   zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_GetSdRecodeFlag(void)
{
    if(g_pSynSampleDataMaster != NULL)
    {
        return (int32_t)g_pSynSampleDataMaster->allowSdRecodeFlag;
    }
    else
    {
        return Std_False;
    }
}

/*!
 * @brief       清除SD卡记录标志
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-04-14   zzk       Create             \n
 *
 */
int32_t SynSampleDataMaster_ClearSdRecodeFlag(void)
{
    if(g_pSynSampleDataMaster == NULL)
    {
        return Std_Ret_ERR;
    }

    g_pSynSampleDataMaster->allowSdRecodeFlag = (uint16_t)Std_False;
    
    return Std_Ret_OK;
}

/*!
 * @brief       获取同步信息
 *
 * @param[in]   void
 * @return
 * @retval      None
 * @par         modify    log
 * Date         Author    Description             \n
 * 2023-04-14   zzk       Create             \n
 *
 */
Syn_Sample_Data_Master_Stru *SynSampleDataMaster_GetSynchroInfo(void)
{
    if(g_pSynSampleDataMaster != NULL)
    {
        return g_pSynSampleDataMaster;
    }
    else
    {
        return NULL;
    }
}


