#include <string.h>
#include "UartProtocol.h"
#include "PicBin.h"
#include <stdint.h>
#include "UDS_ISO14229_Services.h"
#include "flash.h"

#define NULL 0
extern uint8_t UartRevBuff[0x1000];
extern uint32_t UartRevCnts;

uint8_t *GetUartRecvData(uint32_t *UartRecvBufLen, uint32_t *UartRecvPos)
{
    *UartRecvBufLen = 0x1000;
    *UartRecvPos = UartRevCnts;
    return UartRevBuff;
}

void UartSendData(uint8_t *data, uint32_t len)
{
    mwAmt630hUartSendData(data, len);
}

void DisplayNum(uint8_t page, DISPLAY_NUM_ST *pNumData, int32_t NumVal)
{
    uint8_t j = 0;
    uint8_t i = 0;
    int32_t TmpNum;
    uint16_t tmpIndex = 0;
    uint8_t PointFrontRearBlank = 2;
    uint16_t DotPosition = 0;
    uint8_t DotInterval = 0;
	uint16_t NumberList[20];
    DotInterval = 3;
    DotPosition = pNumData->DecimalNum;
    DotPosition <<= 8;
    TmpNum = NumVal;
    if (TmpNum < 0) {        
        TmpNum = -TmpNum;
    }
    do {
        NumberList[tmpIndex ++] = pNumData->NumList[(TmpNum % 10)];
        i++;
        TmpNum /= 10;
        if (i == pNumData->DecimalNum) {
            if (pNumData->NumList[NUM_POINT] != NULL) {
		        NumberList[tmpIndex ++] = pNumData->NumList[NUM_POINT];
            }
        }
    } while (TmpNum != 0u);
    if (pNumData->DecimalNum != 0u) {
        while ((i - 1u) < pNumData->DecimalNum) {
            NumberList[tmpIndex ++] = pNumData->NumList[0];
            i++;
            if (i == pNumData->DecimalNum) {
                if (pNumData->NumList[NUM_POINT] != NULL) {
		            NumberList[tmpIndex ++] = pNumData->NumList[NUM_POINT];
                }
            }
        }
    }
    if (pNumData->MinDigits != 0u) {
        if ((i - 1) < pNumData->MinDigits) {
            for (j = i; j < pNumData->MinDigits; j++) {
                NumberList[tmpIndex ++] = pNumData->NumList[0];
                i++;
            }
        }
    }
    if (NumVal < 0) {
        if (pNumData->NumList[NUM_LINE] != NULL) {
            NumberList[tmpIndex ++] = pNumData->NumList[NUM_LINE];
        }
    }
    
    SetPagePicGroup(page, pNumData->NumInterval, pNumData->x, pNumData->y, NumberList, GROUP_ALIGN_CENTER | (tmpIndex & 0x3f), DotPosition | DotInterval, TFT_ROT_0);
}

/***************** Read 630 ************************/
#define READ_MCU_DATA_MAX 0x40
enum {
    READ630_IDLE,
    READ630_WAITING_RESP,
    READ630_RECV_RESP_DATA,
    READ630_RECV_OFFSET_LEN,
    READ630_RECV_BACKUP_DATA_RESP,
    READ630_RECV_BACKUP_DATA_CRC,
};

uint8_t ReadDataBuf[READ_MCU_DATA_MAX]; /* 读取缓存 */
uint32_t NeedWriteSize; /* 需要写入文件的长度 */
uint32_t FactOffset;    /* 绝对地址 */
uint32_t AppOffset;
uint32_t Check_Upgrade;
uint32_t Check_Upgrade_Cnt;

static uint8_t Read630State = READ630_IDLE;
static uint32_t ReqDataBufAddr = 0;
static uint32_t ReqDataLen = 0;
static uint32_t RespDataOffset = 0;
static uint32_t RespDataLen = 0;
static uint32_t RespDataCrc = 0;
static uint32_t WriteBackupDataCrc = 0;
uint32_t ProcMcuOrBackupData(READ_ARK630_CMD type, uint32_t offset, uint32_t len, uint8_t uotbuffer[])
{
    uint32_t ret32 = 0;

    if (type == REQ_DATA) {
        if (len <= READ_MCU_DATA_MAX) {
            ReqDataBufAddr = (uint32_t)uotbuffer;
            ReqDataLen = len;
            memset((uint8_t *)ReqDataBufAddr, 0, ReqDataLen);
            PackedTransfer_GetMcuData(offset, (uint16_t)len);
            Read630State = READ630_WAITING_RESP;
            RespDataOffset = 0;
            RespDataLen = 0;
        } else {
            ret32 = 1;
        }
    } else if (type == WRITE_BACKUP_DATA) {
        if (len <= READ_MCU_DATA_MAX) {
            PackedTransfer_WriteBackupData(offset, uotbuffer, (uint16_t)len);
            Read630State = READ630_WAITING_RESP;
            RespDataOffset = 0;
            RespDataLen = 0;
        } else {
            ret32 = 1;
        }
    } else if (type == GET_BACKUP_DATA_CRC) {
        PackedTransfer_GetBackupDataCrc(offset, len);
        Read630State = READ630_WAITING_RESP;
        RespDataOffset = 0;
        RespDataLen = 0;
    } else if (type == GET_STATUS) {
        if (Read630State == READ630_WAITING_RESP) {
            ret32 = 2;
        } else if (Read630State == READ630_RECV_RESP_DATA) {
            ret32 = RespDataOffset + RespDataLen;
        } else if (Read630State == READ630_RECV_OFFSET_LEN) {
            ret32 = RespDataOffset;
        } else if (Read630State == READ630_RECV_BACKUP_DATA_CRC) {
            ret32 = RespDataCrc;
        } else if (Read630State == READ630_RECV_BACKUP_DATA_RESP) {
            ret32 = RespDataOffset + RespDataLen;
        } else {
            Read630State = READ630_IDLE;
        }
    } else if ((type == GET_APP_DATA_OFFSET) || (type == GET_BACKUP_DATA_OFFSET)) {
        PackedTransfer_GetDataOffsetLen(type);
        Read630State = READ630_WAITING_RESP;
        RespDataOffset = 0;
        RespDataLen = 0;
    } else {
        ;
    }

    return ret32;
}

void GetDataBuf(uint32_t *pAddr, uint32_t *pLen)
{
    *pAddr = ReqDataBufAddr;
    *pLen = ReqDataLen;
}

void SetRecvDataSt(RECV_MCU_DATA_TYPE type, uint32_t addr, uint32_t len, uint32_t crc)
{
    RespDataOffset = addr;
    RespDataLen = len;
    RespDataCrc = crc;
    if (type == RECV_TYPE_DATA) {
        Read630State = READ630_RECV_RESP_DATA;
    } else if (type == RECV_TYPE_OFFSET_LEN) {
        Read630State = READ630_RECV_OFFSET_LEN;
    } else if (type == RECV_TYPE_WRITE_BACKUP_RESP) {
        Read630State = READ630_RECV_BACKUP_DATA_RESP;
        WriteBackupDataCrc = crc;
    } else if (type == RECV_TYPE_BACKUP_CRC) {
        Read630State = READ630_RECV_BACKUP_DATA_CRC;
    } else {
        ;
    }
}
/***************** Read 630 end ************************/

void GetReadInfo(READ_ARK630_CMD type)
{
    static uint8_t readSt = 0;
    static uint16_t getStRetryCnts = 0;
    uint32_t tmpRet;

    if (NeedWriteSize == 0)
    {
        if (readSt == 0)
        {
            readSt = 1;
            ProcMcuOrBackupData(type, 0, 0, 0); /* 获取偏移地址 */
            getStRetryCnts = 500;
        }
        else
        {
            tmpRet = ProcMcuOrBackupData(GET_STATUS, 0, 0, 0);
            if ((tmpRet != 2) || (--getStRetryCnts == 0)) /* 非零值为获得的程序地址 */
            {
                if (tmpRet != 2)
                {
                    NeedWriteSize = 32; /* 此时的NeedWriteSize不重要, 只要跳出循环就行 */
                    if (type == GET_APP_DATA_OFFSET)
                    {
                        FactOffset = 0; /* USB按相对地址获取数据 */
                    }
                    AppOffset = 0x00;
                }
                readSt = 0;
            }
        }
    }
}

/**
 * @brief 检查Flash中的MCU程序信息, 是否与当前运行的MCU_APP信息相同, 若不同, 则进入升级模式
 */
void Check_MCU_in_Flash(READ_ARK630_CMD type)
{
    static uint8_t readSt = 0;
    static uint16_t getStRetryCnts = 0;

    uint32_t tmpLen;
    uint8_t saveVersion[16];
    uint8_t readVersion[16];

    if (NeedWriteSize != 0)
    {
        if (readSt == 0)
        {
            readSt = 1;
            (void)memset(ReadDataBuf, 0xFFU, sizeof(ReadDataBuf)); /* 初始化buffer */
            ProcMcuOrBackupData(REQ_DATA, FactOffset, READ_MCU_DATA_MAX, ReadDataBuf); // 按地址获取程序数据
            getStRetryCnts = 500;
        }
        else
        {
            tmpLen = ProcMcuOrBackupData(GET_STATUS, 0, 0, 0); /* 获取读取状态 */
            if (FactOffset + READ_MCU_DATA_MAX == tmpLen)             /* 当返回值为目标位置时为数据获取成功 */
            {
                if (AppOffset == 0) /* 首个数据块内解析文件信息 */
                {
                    if (type == GET_APP_DATA_OFFSET) /* 从 MCU_APP 升级文件 */
                    {
                        flash_read(FLASH_630H_UPDATE_INFO, sizeof(saveVersion), saveVersion); /* 读取630H升级记录 */

                        memcpy(readVersion, &ReadDataBuf[16], 16);          /* 630中读出的版本信息 */
                        if (memcmp(readVersion, saveVersion, 16) != 0) /* 对比版本不同才更新 */
                        {
                            Get_Into_630H_Update_MCU_Mode();
                        }
                        else
                        {
                            /* 信息相同, 重置状态 */
                            NeedWriteSize = 0;
                            Check_Upgrade = 0;
                            readSt = 0;
                        }
                    }
                }
            }
            if (--getStRetryCnts == 0)
            {
                /* 读信息超时, 重置状态 */
                readSt = 0;
            }
        }
    }
}

void Check_MCU_Info_in_630H(void)
{
    
    if(Check_Upgrade == 1U)
    {
        GetReadInfo(GET_APP_DATA_OFFSET);
        Check_MCU_in_Flash(GET_APP_DATA_OFFSET);
    }
    else
    {
        Check_Upgrade_Cnt++;
        if(Check_Upgrade_Cnt >= 2500U) /* 放在2ms任务中, 2500 = 5000ms */
        {
            Check_Upgrade_Cnt = 0;
            Check_Upgrade = 1U;
        }
    }
}