#include "Arb_State_Vote.h"
#include "Arb_State.h"

/**仅在状态表决时使用，简化宏，只包含区域状态 */
#define VOTE_STATE_CTRL (&(AREA_STATE_CTRL_PTR->StateArea))

/**
 * @brief 宕机状态转换
 */
void s_Shutdown_vote(void);
/**
 * @brief 未知地状态转换
 */
void s_Unknown_vote(void);
/**
 * @brief 离线地状态转换
 */
void s_Offline_vote(void);
/**
 * @brief 主地状态转换
 */
void s_Master_vote(void);
/**
 * @brief 备地状态转换
 */
void s_Slave_vote(void);

void Area_With_Arb_State_Vote(void)
{
    ENUM_AREA_STATE local_state = VOTE_STATE_CTRL->Local_state;
    switch(local_state)
    {
        case ENUM_AREA_SHUTDOWN:
            s_Shutdown_vote();
            break;
        case ENUM_AREA_UNKNOW:
            s_Unknown_vote();
            break;
        case ENUM_AREA_OFFLINE:
            s_Offline_vote();
            break;
        case ENUM_AREA_MASTER:
            s_Master_vote();
            break;
        case ENUM_AREA_SLAVE:
            s_Slave_vote();
            break;
        default:
            AREA_LOG_MSG("AREA_STATE_VOTE:Invalid local state:%d\n", local_state);
            break;

    }
}
/**
 * @brief 宕机状态转换
 */
void s_Shutdown_vote(void)
{
	VOTE_STATE_CTRL->Local_state = ENUM_AREA_SHUTDOWN;
    AREA_LOG_MSG("AREA_STATE_VOTE:Local is Shutdown, system will assert\n");
    CM_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
}
/**
 * @brief 未知地状态转换
 */
void s_Unknown_vote(void)
{
    CM_BOOL Sync_Health_Flag = AREA_FLAGS_CTRL_PTR->Sync_Health_Flag; /**同步成功标志 */
    /**获取另外三系状态 */
    ENUM_AREA_STATE Partner_State = VOTE_STATE_CTRL->Partner_state;
    ENUM_AREA_STATE Area_A_State = VOTE_STATE_CTRL->Partner_Area_A_state;
    ENUM_AREA_STATE Area_B_State = VOTE_STATE_CTRL->Partner_Area_B_state;
    /**初始化未知地计数 */
    static CM_UINT32 s_unkown_cnt = 0u;
    /**状态转换部分 */
    if(0x55u == AREA_ARB_CTRL_PTR->Arb_Ack)
    {
        /**收到仲裁升主回复 */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER;
        AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Master, Arbitration ACK received\n");
    }
    else if(ENUM_AREA_MASTER == Partner_State)
    {
        /**和主地在同一地 */
        if(CM_TRUE == Sync_Health_Flag)
        {
            VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER;
            AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Master, Partner is Master, Sync Sucess\n");
        }
        else
        {
            VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE;
            AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Offline, Partner is Master, Sync Fail\n");
        }
    }
    else if((ENUM_AREA_UNKNOW == Area_A_State || ENUM_AREA_UNKNOW == Area_B_State) 
        && (MSCP_AREA_ID_B == AREA_BASIC_CFG_PTR->AreaID))
    {
        /**另一地是离线地，本地是B地，降离线 */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE;
        AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Offline, A is Unknown, Local is B\n");
    }
    else if((ENUM_AREA_SLAVE == Area_A_State || ENUM_AREA_SLAVE == Area_B_State))
    {
        /**另一地是备地，降离线（暂不存在改场景，预留转换） */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE;
        AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Offline, Another Area is Slave\n");
    }
    else if((ENUM_AREA_MASTER == Area_A_State || ENUM_AREA_MASTER == Area_B_State))
    {
        /**另一地是主地，降离线 */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE;
        AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Offline, Another Area is Master\n");
    }
    else if((MSCP_AREA_ID_A == AREA_BASIC_CFG_PTR->AreaID)
        && (ENUM_AREA_UNKNOW == Area_A_State || ENUM_AREA_OFFLINE == Area_A_State) 
        && (ENUM_AREA_UNKNOW == Area_B_State || ENUM_AREA_OFFLINE == Area_B_State))
    {
        /**另一地为未知地/离线地，本地是A地，维持10周期升主（另一地是宕机时等待仲裁回复） */
        s_unkown_cnt++;
        if(s_unkown_cnt > MSCP_AREA_UNKNOW_COUNT_MAX)
        {
            VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER;
            AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Master, Local A tolerated %d cycles\n",
                s_unkown_cnt);
            s_unkown_cnt = 0u;
        }
    }
    else
    {
        /**维持未知地 */
    }
    /**离开未知地，清空计数 */
    if(ENUM_AREA_UNKNOW != VOTE_STATE_CTRL->Local_state)
    {
        s_unkown_cnt = 0u;
    }
}
/**
 * @brief 离线地状态转换
 */
void s_Offline_vote(void)
{
    CM_BOOL Sync_Health_Flag = AREA_FLAGS_CTRL_PTR->Sync_Health_Flag; /**同步成功标志 */
    CM_UINT8 id_mm = AreaArb_GetID_byState(ENUM_AREA_MASTER, ENUM_2x2_MASTER); /**主地主的ID */
    /**状态转换 */
    if(CM_TRUE == Sync_Health_Flag)
    {
        /**同步成功 */
        if(ENUM_AREA_MASTER == VOTE_STATE_CTRL->Partner_state)
        {
            /**主地在本地，升主地 */
            VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER;
            AREA_LOG_MSG("AREA_STATE_VOTE:Offline>>>>>Master, Partner is Master and sync is healthy\n");
        }
        else if(ENUM_AREA_MASTER == VOTE_STATE_CTRL->Partner_Area_A_state ||
            ENUM_AREA_MASTER == VOTE_STATE_CTRL->Partner_Area_B_state)
        {
            /**主地在另一地，升备地 */
            VOTE_STATE_CTRL->Local_state = ENUM_AREA_SLAVE;
            AREA_LOG_MSG("AREA_STATE_VOTE:Offline>>>>>Slave, Another Area is Master and sync is healthy\n");
        }
        else
        {

        }
    }
    else if(0u == id_mm && 0)
    {
        /**(预留)主地主ID不存在，认为主地主宕机，离线地降未知地 */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_UNKNOW;
        AREA_LOG_MSG("AREA_STATE_VOTE:Offline>>>>>Unknow, Master board not found\n");
    }
    else
    {

    }
    
}
/**
 * @brief 主地状态转换
 */
void s_Master_vote(void)
{
    ENUM_2x2_STATE_T state2x = AREA_STATE_CTRL_PTR->State2x.LocalState;

    if(ENUM_AREA_MASTER == VOTE_STATE_CTRL->Partner_Area_A_state || ENUM_AREA_MASTER == VOTE_STATE_CTRL->Partner_Area_B_state)
    {
        /**双主宕机 */
        AREA_LOG_MSG("AREA_STATE_VOTE:Double master detected, Another Area state:%d-%d\n",
            VOTE_STATE_CTRL->Partner_Area_A_state, VOTE_STATE_CTRL->Partner_Area_B_state);
        CM_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
    }
    else if(ENUM_2x2_OFFLINE == state2x)
    {
        /**与主地主同步失败 */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE;
        AREA_LOG_MSG("AREA_STATE_VOTE:Master>>>>>Offline, Sync failed\n");
    }
    else
    {

    }
}
/**
 * @brief 备地状态转换
 */
void s_Slave_vote(void)
{
    CM_BOOL flag_comm_mm_status = CM_FALSE; /**与主地主的通信状态 */
    CM_UINT8 id_mm = AreaArb_GetID_byState(ENUM_AREA_MASTER, ENUM_2x2_MASTER); /**主地主的ID */
    AreaArb_GetCommStatus_byID(id_mm, NULL, &flag_comm_mm_status);

    ENUM_2x2_STATE_T state2x = AREA_STATE_CTRL_PTR->State2x.LocalState;

    if(0x55u == AREA_ARB_CTRL_PTR->Arb_Ack)
    {
        /**收到仲裁升主回复 */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER;
        AREA_LOG_MSG("AREA_STATE_VOTE:Slave>>>>>Master, Arbitration ACK received\n");
    }
    else if(ENUM_2x2_OFFLINE == state2x)
    {
        /**同步失败 */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE;
        AREA_LOG_MSG("AREA_STATE_VOTE:Slave>>>>>Offline, Sync failed and Master ID:%d exists\n",
            id_mm);
    }
    else if(ENUM_AREA_MASTER == VOTE_STATE_CTRL->Partner_state)
    {
        /**对系是主地，升主地(备地主升主地主后，备地备通过这条逻辑升主地) */
        VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER;
        AREA_LOG_MSG("AREA_STATE_VOTE:Slave>>>>>Master, Partner is Master\n");
    }
    else
    {

    }
}
