#include "CAN_Lib.h"

typedef struct
{
    canlib_uint32_t u32MsgID;
    canlib_uint32_t u32Timer;
    canlib_uint32_t u32MsgCycle;
    canlib_uint32_t u32SendCnt;
    canlib_uint8_t  u8MsgSTD_EXT;
    canlib_uint8_t  u8MsgPro;
    canlib_uint8_t  u8TXMsgType;
    canlib_uint8_t  u8MsgRet;
    canlib_uint8_t  u8MsgBuff [ 8u ];
    canlib_uint16_t u16MsgDLC;
    canlib_uint16_t u16TXMsgDIMcounter;
} st_CAN_SendOperation;

typedef struct
{
    const st_CAN_SendAttribute *pCAN_SendAttribute;
    st_CAN_SendOperation *      CanMsg;
    canlib_uint16_t             Total_Msg;
    HAL_CAN_Send                Can_Write;
} st_CanMsgTxOp;

st_CanMsgTxOp  CanMsgTxOp;
canlib_uint8_t u8CAN_TX_ENABLE;

void CAN_TX_DiagCtrlEnable(canlib_uint8_t TX_enable)
{
    u8CAN_TX_ENABLE = TX_enable;
    u8CAN_TX_ENABLE |= 0x80u;
}

void CAN_TX_DiagCtrlRelease(void)
{
    u8CAN_TX_ENABLE &= ~(0x01u << 7);
}

void CAN_TX_SetEnable(canlib_uint8_t TX_enable)
{
    if ( (u8CAN_TX_ENABLE & 0x80u) == 0x80u )
    {
    }
    else
    {
        u8CAN_TX_ENABLE = TX_enable;
    }
}

canlib_uint8_t CAN_TX_ReadEnableSts(void)
{
    return u8CAN_TX_ENABLE;
}

CAN_FUNC_ERR_t Can_TX_BuffInit(canlib_uint8_t *MemSpace, const st_CAN_SendAttribute *Array, canlib_uint16_t length, HAL_CAN_Send pfunc)
{
    canlib_uint8_t i              = 0u;
    canlib_uint8_t j              = 0u;
    CAN_FUNC_ERR_t ret            = CAN_ERR_OK;
    CanMsgTxOp.pCAN_SendAttribute = Array;
    CanMsgTxOp.CanMsg             = ( st_CAN_SendOperation * )(( void * )MemSpace);
    CanMsgTxOp.Total_Msg          = length;
    CanMsgTxOp.Can_Write          = pfunc;
    u8CAN_TX_ENABLE               = 0X00U;
    for ( i = 0u; i < CanMsgTxOp.Total_Msg; i++ )
    {
        CanMsgTxOp.CanMsg [ i ].u32MsgID     = CanMsgTxOp.pCAN_SendAttribute [ i ].u32MsgID;
        CanMsgTxOp.CanMsg [ i ].u32Timer     = CanMsgTxOp.pCAN_SendAttribute [ i ].u32MsgCycleOffset;
        CanMsgTxOp.CanMsg [ i ].u32MsgCycle  = CanMsgTxOp.pCAN_SendAttribute [ i ].u32MsgCycle;
        CanMsgTxOp.CanMsg [ i ].u32SendCnt   = CanMsgTxOp.pCAN_SendAttribute [ i ].u32InitSendCnt;
        CanMsgTxOp.CanMsg [ i ].u8MsgSTD_EXT = CanMsgTxOp.pCAN_SendAttribute [ i ].u8MsgSTD_EXT;
        CanMsgTxOp.CanMsg [ i ].u8MsgPro     = CanMsgTxOp.pCAN_SendAttribute [ i ].u8MsgPro;
        CanMsgTxOp.CanMsg [ i ].u16MsgDLC    = CanMsgTxOp.pCAN_SendAttribute [ i ].u8MsgDLC;
        CanMsgTxOp.CanMsg [ i ].u8TXMsgType  = CanMsgTxOp.pCAN_SendAttribute [ i ].u8TXMsgType;
        CanMsgTxOp.CanMsg [ i ].u8MsgRet     = 0u;

        /*
        发送周期是 0表示纯事件型报文    DIM counter 需要是0
        发送周期不是 0 分为如下两种
        1.周期报文  DIM 无意义 初始化成0
        2.周期事件型 DIM 初始化成0xffff
        */
        if ( CanMsgTxOp.pCAN_SendAttribute [ i ].u32MsgCycle != 0ul )
        {
            if ( CanMsgTxOp.pCAN_SendAttribute [ i ].u8TXMsgType == 0u )
            {
                CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter = 0xffffu;
            }
            else
            {
                CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter = 0xffffu;
            }
        }
        else
        {
            if ( CanMsgTxOp.pCAN_SendAttribute [ i ].u8TXMsgType != 0u )
            {
                CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter = 0u;
            }
            else
            {
                CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter = 0u;
                /*while (1u)*/
                {
                    ret = CAN_ERR_ParaInit;
                    /*这里不应该达到,不应该有这个组合,写的不对,早死早超生吧*/
                    /*你在表格里定义了一个周期型的报文,你发送周期还给我填个0.
                     * 还是死这里吧.别出去霍霍人了.*/
                }
            }
        }

        for ( j = 0u; j < CanMsgTxOp.CanMsg [ i ].u16MsgDLC; j++ )
        {
            CanMsgTxOp.CanMsg [ i ].u8MsgBuff [ j ] = 0u;
        }
        if ( CanMsgTxOp.pCAN_SendAttribute [ i ].MsgBufferSet != (( void * )0) )
        {
            CanMsgTxOp.pCAN_SendAttribute [ i ].MsgBufferSet(CanMsgTxOp.CanMsg [ i ].u8MsgBuff);
        }
    }
    return ret;
}

void Can_Write_Fun(canlib_uint32_t u32CbkCycle)
{
    canlib_uint8_t i = 0u;
    canlib_uint8_t j = 0u;
    st_CAN_Msg     m_Msg;
    if ( (u8CAN_TX_ENABLE & 0x7Fu) == 0X55U )
    {
        for ( i = 0u; i < CanMsgTxOp.Total_Msg; i++ )
        {
            if ( CanMsgTxOp.CanMsg [ i ].u8TXMsgType == 0u )
            {
                if ( CanMsgTxOp.CanMsg [ i ].u32Timer < CanMsgTxOp.CanMsg [ i ].u32MsgCycle )
                {
                    CanMsgTxOp.CanMsg [ i ].u32Timer += u32CbkCycle;
                }
                else
                {
                    if ( CanMsgTxOp.CanMsg [ i ].u32SendCnt <= 0xffff0000ul )
                    {
                        CanMsgTxOp.CanMsg [ i ].u32SendCnt++;
                    }
                    if ( CanMsgTxOp.CanMsg [ i ].u8MsgRet == 0U )
                    {
                        for ( j = 0u; j < CanMsgTxOp.CanMsg [ i ].u16MsgDLC; j++ )
                        {
                            CanMsgTxOp.CanMsg [ i ].u8MsgBuff [ j ] = 0u;
                        }
                        if ( CanMsgTxOp.pCAN_SendAttribute [ i ].MsgBufferSet != (( void * )0) )
                        {
                            CanMsgTxOp.pCAN_SendAttribute [ i ].MsgBufferSet(CanMsgTxOp.CanMsg [ i ].u8MsgBuff);
                        }
                    }
                    /*  Below HW SEND INTERFACE */
                    m_Msg.MsgID  = CanMsgTxOp.CanMsg [ i ].u32MsgID;
                    m_Msg.MsgStd = CanMsgTxOp.CanMsg [ i ].u8MsgSTD_EXT;
                    m_Msg.MsgRTR = 0u;
                    m_Msg.MsgDLC = ( canlib_uint8_t )CanMsgTxOp.CanMsg [ i ].u16MsgDLC;
                    m_Msg.MsgPro = CanMsgTxOp.CanMsg [ i ].u8MsgPro;

                    for ( j = 0u; j < CanMsgTxOp.CanMsg [ i ].u16MsgDLC; j++ )
                    {
                        m_Msg.Msg [ j ] = Load_AttrBuff [ i ].sig.Msg [ j ];
                    }

                    if ( CanMsgTxOp.Can_Write != (( void * )0) )
                    {
                        CanMsgTxOp.CanMsg [ i ].u8MsgRet = CanMsgTxOp.Can_Write(&m_Msg);
                    }

                    if ( CanMsgTxOp.CanMsg [ i ].u8MsgRet == 0U )
                    {
                        CanMsgTxOp.CanMsg [ i ].u32Timer = 0u;
                    }
                    else
                    {
                        CanMsgTxOp.CanMsg [ i ].u32Timer -= u32CbkCycle;
                    }
                }
            }
            else
            {
                if ( CanMsgTxOp.CanMsg [ i ].u32MsgCycle != 0x00ul )
                {
                    if ( CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter != 0x00ul )
                    {
                        if ( (CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter != CanMsgTxOp.CanMsg [ i ].u32SendCnt) || (CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter == 0xffffu) )
                        {
                            if ( CanMsgTxOp.CanMsg [ i ].u32Timer < CanMsgTxOp.CanMsg [ i ].u32MsgCycle )
                            {
                                CanMsgTxOp.CanMsg [ i ].u32Timer += u32CbkCycle;
                            }
                            else
                            {
                                CanMsgTxOp.CanMsg [ i ].u32Timer = 0u;
                                if ( CanMsgTxOp.CanMsg [ i ].u32SendCnt <= 0xffff0000ul )
                                {
                                    CanMsgTxOp.CanMsg [ i ].u32SendCnt++;
                                }
                                for ( j = 0u; j < CanMsgTxOp.CanMsg [ i ].u16MsgDLC; j++ )
                                {
                                    CanMsgTxOp.CanMsg [ i ].u8MsgBuff [ j ] = 0u;
                                }
                                if ( CanMsgTxOp.pCAN_SendAttribute [ i ].MsgBufferSet != (( void * )0) )
                                {
                                    CanMsgTxOp.pCAN_SendAttribute [ i ].MsgBufferSet(CanMsgTxOp.CanMsg [ i ].u8MsgBuff);
                                }
                                /*  Below HW SEND INTERFACE */
                                m_Msg.MsgID  = CanMsgTxOp.CanMsg [ i ].u32MsgID;
                                m_Msg.MsgStd = CanMsgTxOp.CanMsg [ i ].u8MsgSTD_EXT;
                                m_Msg.MsgRTR = 0u;
                                m_Msg.MsgDLC = ( canlib_uint8_t )CanMsgTxOp.CanMsg [ i ].u16MsgDLC;
                                m_Msg.MsgPro = CanMsgTxOp.CanMsg [ i ].u8MsgPro;

                                for ( j = 0u; j < CanMsgTxOp.CanMsg [ i ].u16MsgDLC; j++ )
                                {
                                    m_Msg.Msg [ j ] = CanMsgTxOp.CanMsg [ i ].u8MsgBuff [ j ];
                                }
                                if ( CanMsgTxOp.Can_Write != (( void * )0) )
                                {
                                    CanMsgTxOp.CanMsg [ i ].u8MsgRet = CanMsgTxOp.Can_Write(&m_Msg);
                                }
                                if ( CanMsgTxOp.CanMsg [ i ].u8MsgRet == 0U )
                                {
                                    CanMsgTxOp.CanMsg [ i ].u32Timer = 0u;
                                }
                                else
                                {
                                    CanMsgTxOp.CanMsg [ i ].u32Timer -= u32CbkCycle;
                                }
                            }
                        }
                        else
                        {
                            if ( CanMsgTxOp.pCAN_SendAttribute [ i ].u32MsgCycle != 0ul )
                            {
                                CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter = 0xffffu;
                            }
                            else
                            {
                                CanMsgTxOp.CanMsg [ i ].u16TXMsgDIMcounter = 0u;
                                CanMsgTxOp.CanMsg [ i ].u32MsgCycle        = 0ul;
                            }
                            CanMsgTxOp.CanMsg [ i ].u32SendCnt = 0ul;
                        }
                    }
                }
            }
        }
    }
}

/*
u32TxMsgCycle

ret = 0  success
ret = 1  wrong attribute
ret = 2  request out of range
 */
CAN_FUNC_ERR_t Can_Msg_Tx_Overwrite(canlib_uint32_t u32TxMsgIdx, canlib_uint16_t u16TxMSgDIMcounter, canlib_uint32_t u32TxMsgCycle)
{
    CAN_FUNC_ERR_t Ret = CAN_ERR_OK;
    if ( u32TxMsgIdx < CanMsgTxOp.Total_Msg )
    {
        if ( CanMsgTxOp.CanMsg [ u32TxMsgIdx ].u8TXMsgType != 0u )
        {
            CanMsgTxOp.CanMsg [ u32TxMsgIdx ].u16TXMsgDIMcounter = u16TxMSgDIMcounter;
            CanMsgTxOp.CanMsg [ u32TxMsgIdx ].u32MsgCycle        = u32TxMsgCycle;
            CanMsgTxOp.CanMsg [ u32TxMsgIdx ].u32SendCnt         = 0ul;
        }
        else
        {
            Ret = CAN_ERR_ParaInit;
        }
    }
    else
    {
        Ret = CAN_ERR_OUTRANGE;
    }
    return Ret;
}

CAN_FUNC_ERR_t Can_Msg_TX_FastInitCycle(canlib_uint32_t u32TxMsgIdx, canlib_uint32_t CurTimerCnt)
{
    CAN_FUNC_ERR_t Ret = CAN_ERR_OK;
    if ( u32TxMsgIdx < CanMsgTxOp.Total_Msg )
    {
        CanMsgTxOp.CanMsg [ u32TxMsgIdx ].u32Timer = CurTimerCnt;
    }
    else
    {
        Ret = CAN_ERR_OUTRANGE;
    }
    return Ret;
}

void Can_Msg_TX_SUCCESS(canlib_uint32_t u32TxMsgIdx)
{
    if ( u32TxMsgIdx < CanMsgTxOp.Total_Msg )
    {
        if ( CanMsgTxOp.pCAN_SendAttribute [ u32TxMsgIdx ].MsgSuccess != (( void * )0) )
        {
            CanMsgTxOp.pCAN_SendAttribute [ u32TxMsgIdx ].MsgSuccess( );
        }
    }
}

canlib_uint32_t Read_CAN_TX_Version(void)
{
    return 0x0004u;
}
