#include "CAN_Lib.h"

typedef struct
{
    canlib_uint8_t          AnalyzeMsg [ 8u ];
    canlib_uint8_t          ReceiveBuf [ 8u ];
    volatile canlib_uint8_t CAN_Busy;
    volatile canlib_uint8_t CAN_Received;
    canlib_uint8_t          CAN_Status;
    canlib_uint8_t          CAN_Reverse;
    canlib_uint32_t         CAN_Lost;
} st_CANMsgStruct;

typedef struct
{
    st_CANMsgStruct *         CAN_MSG_Analysis;
    const st_CANMsgAttribute *pAttrubute;
    canlib_uint16_t           Total_Msg;
} st_CanMsgOp;

st_CanMsgOp    CanRXMsgOp;
canlib_uint8_t u8CAN_RX_ENABLE;
#if defined(__ICCARM__)
const char DataStr [] = {__DATE__};
const char TimeStr [] = {__TIME__};
#elif defined(__ghs__)
const char DataStr [] = {__DATE__};
const char TimeStr [] = {__TIME__};
#elif defined(__GNUC__)
const char DataStr [] = {__DATE__};
const char TimeStr [] = {__TIME__};
#else

#endif

void CAN_RX_SetEnable(canlib_uint8_t RX_enable)
{
    if ( (u8CAN_RX_ENABLE & 0x80u) == 0x80u )
    {
    }
    else
    {
        u8CAN_RX_ENABLE = RX_enable;
    }
}
canlib_uint8_t CAN_RX_ReadEnableSts(void)
{
    return u8CAN_RX_ENABLE;
}

void Can_RX_BuffInit(canlib_uint8_t *memSpace, const st_CANMsgAttribute *array, canlib_uint16_t length)
{
    canlib_uint16_t i;
    canlib_uint8_t  j;

    CanRXMsgOp.pAttrubute       = array;
    CanRXMsgOp.CAN_MSG_Analysis = ( st_CANMsgStruct * )(( void * )memSpace);
    CanRXMsgOp.Total_Msg        = length;
    for ( i = 0u; i < CanRXMsgOp.Total_Msg; i++ )
    {
        for ( j = 0u; j < 8u; j++ )
        {
            CanRXMsgOp.CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] = CanRXMsgOp.pAttrubute [ i ].INIT_Aarry [ j ];
            CanRXMsgOp.CAN_MSG_Analysis [ i ].ReceiveBuf [ j ] = CanRXMsgOp.pAttrubute [ i ].INIT_Aarry [ j ];
        }
        CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Busy     = 0U;
        CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Received = 0U;
        CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Status   = 0U;
        CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Reverse  = 0U;
        CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Lost     = 0U;
    }
    u8CAN_RX_ENABLE = 0u;
}

void CanMSg_XMS_Analysis(canlib_uint16_t CbkCycle)
{
    canlib_uint16_t i;
    canlib_uint8_t  j;
    if ( (u8CAN_RX_ENABLE&0x7fu) == 0x00u )
    {
        for ( i = 0u; i < CanRXMsgOp.Total_Msg; i++ )
        {
            if ( CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Received == 1u )
            {
                CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Busy = 1u;
                for ( j = 0u; j < 8u; j++ )
                {
                    CanRXMsgOp.CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] = CanRXMsgOp.CAN_MSG_Analysis [ i ].ReceiveBuf [ j ];
                }
                CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Busy     = 0u;
                CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Received = 0u;
                CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Lost     = 0u;
                CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Status   = 0u;

                if ( CanRXMsgOp.pAttrubute [ i ].Msg_ProcessCBK != (( void * )0) )
                {
                    CanRXMsgOp.pAttrubute [ i ].Msg_ProcessCBK(CanRXMsgOp.CAN_MSG_Analysis [ i ].AnalyzeMsg);
                }
            }

            if ( (CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Lost >= CanRXMsgOp.pAttrubute [ i ].MSG_TIMEOUT_VAL) && (CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Status != 0x55U) )
            {
                CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Status = 0x55U;
                for ( j = 0u; j < 8u; j++ )
                {
                    CanRXMsgOp.CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] &= CanRXMsgOp.pAttrubute [ i ].MASK_Array [ j ];
                    CanRXMsgOp.CAN_MSG_Analysis [ i ].AnalyzeMsg [ j ] |= CanRXMsgOp.pAttrubute [ i ].TIMEOUT_Array [ j ];
                }
                if ( CanRXMsgOp.pAttrubute [ i ].Msg_LOSTCBK != (( void * )0) )
                {
                    CanRXMsgOp.pAttrubute [ i ].Msg_LOSTCBK(CanRXMsgOp.CAN_MSG_Analysis [ i ].AnalyzeMsg);
                }
            }
            else
            {
                if ( CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Lost < CanRXMsgOp.pAttrubute [ i ].MSG_TIMEOUT_VAL )
                {
                    CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Lost += CbkCycle;
                }
            }
        }
    }
}

void Co_Can_Buff_Set(canlib_uint16_t MsgID, canlib_uint8_t m_DLC, canlib_uint8_t Msg [])
{
    canlib_uint8_t  i;
    canlib_uint16_t u16ConverIdx;
    u16ConverIdx = MsgID;
    if ( u16ConverIdx < CanRXMsgOp.Total_Msg )
    {
        if ( CanRXMsgOp.CAN_MSG_Analysis [ u16ConverIdx ].CAN_Busy == 0u )
        {
            for ( i = 0u; i < 8u; i++ )
            {
                CanRXMsgOp.CAN_MSG_Analysis [ u16ConverIdx ].ReceiveBuf [ i ] = Msg [ i ];
            }
            CanRXMsgOp.CAN_MSG_Analysis [ u16ConverIdx ].CAN_Received = 1u;
            if ( CanRXMsgOp.pAttrubute [ u16ConverIdx ].Msg_ReceiveCBK != (( void * )0) )
            {
                CanRXMsgOp.pAttrubute [ u16ConverIdx ].Msg_ReceiveCBK(CanRXMsgOp.CAN_MSG_Analysis [ u16ConverIdx ].ReceiveBuf);
            }
        }
    }
}

canlib_uint8_t CAN_MSG_Read(canlib_uint16_t MsgIdx, canlib_uint8_t BuffIdx)
{
    canlib_uint8_t ret = 0u;
    if ( MsgIdx < CanRXMsgOp.Total_Msg )
    {
        if ( BuffIdx < 8u )
        {
            ret = CanRXMsgOp.CAN_MSG_Analysis [ MsgIdx ].AnalyzeMsg [ BuffIdx ];
        }
        else
        {
            ret = 0u;
        }
    }
    else
    {
        ret = 0u;
    }  
    return ret;
}

canlib_uint8_t CAN_MSG_Status(canlib_uint16_t MsgID)
{
    canlib_uint8_t ret;
    if ( MsgID < CanRXMsgOp.Total_Msg )
    {
        ret = ( canlib_uint8_t )CanRXMsgOp.CAN_MSG_Analysis [ MsgID ].CAN_Status;
    }
    else
    {
        ret = 0u;
    }
    return ret;
}

void Can_RX_ResetAllTimer(void)
{
    canlib_uint16_t i;

    for ( i = 0u; i < CanRXMsgOp.Total_Msg; i++ )
    {
        CanRXMsgOp.CAN_MSG_Analysis [ i ].CAN_Lost = 0U;
    }
}

void Can_RX_ResetTimer(canlib_uint16_t idx)
{
    if ( idx < CanRXMsgOp.Total_Msg )
    {
        CanRXMsgOp.CAN_MSG_Analysis [ idx ].CAN_Lost = 0U;
    }
}

canlib_uint32_t Read_CAN_RX_Version(void)
{
    return 0x0004U;
}

void CAN_RX_DiagCtrlEnable(canlib_uint8_t RX_enable)
{
    u8CAN_RX_ENABLE = RX_enable;
    u8CAN_RX_ENABLE |= 0x80u;
}

void CAN_RX_DiagCtrlRelease(void)
{
    u8CAN_RX_ENABLE &= ~(0x01u << 7);
}