
#include "SOE.h"
#include "stdio.h"
#include "parameter.h"
#include "FM_RTC.h"
#include "flash.h"
#include "capture.h"
#include "task.h"

#define eventsOrderRecordStartAddr 4096

// /* 用于标记SOE擦除 */
// static uint8_t soeFlag = 0;

typedef struct _soeDataInfo {
    uint16_t mode;	            //故障类型 2byte
    timeInfo time;				//时间 6byte
    float temp;                 //故障发生时刻的值 4byte
} soeDataInfo;
#define soeDataInfoSize sizeof(soeDataInfo)

typedef struct _soeSaveInfo {
    soeDataInfo data[5];

    uint8_t insertPos;          //记录插入数据的位置
    uint8_t outPos;             //记录输出数据的位置
    uint8_t count;              //记录可插入数据插入数据个数
    soeDataInfo *insertData;    //指向能插入数据的位置
    soeDataInfo *outData;       //指向能输出数据的位置
} soeSaveInfo;

typedef struct _soeStorageParameters {
    uint16_t len;               //soe下次记录距离0的偏移量
    uint16_t pos;               //下次soe记录的位置
    uint32_t dataLen;           //soe数据总个数
} soeStorageParameters;

static soeSaveInfo soeInfo = {0};
static soeStorageParameters soeParameters = {0};

/**
 * @brief  得到一次事件记录的长度
 * @param
 */
uint16_t getSoeDataInfoSize(void)
{
    return soeDataInfoSize;
}

/**
 * @brief  初始化事件顺序记录
 * @param
 */
void eventsOrderRecordStartInit(void)
{
    read_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters));

    if (soeParameters.len == 0xFFFF && soeParameters.pos == 0xFFFF) {
        soeParameters.len = 0;
        soeParameters.pos = eventsOrderRecordStartAddr + sizeof(soeParameters);
        soeParameters.dataLen = 0;
        write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters));
    }

    else if (soeParameters.len > 100 
        || soeParameters.pos != eventsOrderRecordStartAddr + sizeof(soeParameters) + soeParameters.len * soeDataInfoSize) {
        soeParameters.len = 0;
        soeParameters.pos = eventsOrderRecordStartAddr + sizeof(soeParameters);
        soeParameters.dataLen = 0;
        write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters));
    }

    soeInfo.count = 5;
    soeInfo.insertPos = 0;
    soeInfo.outPos = 0;
    soeInfo.outData = NULL;
    soeInfo.insertData = &soeInfo.data[soeInfo.insertPos];

    // soeFlag = 1;
}

/**
 * @brief  插入事件顺序记录
 * @param
 */
/*
|       故障类型        |   temp    |
| :-------------------: | :-------: |
| firstStageProtection  | 输出电流  |
| secondStageProtection | 输出电流  |
| thirdStageProtection  | 输出电流  |
|     lowInputLoad      | 输出电压  |
|    overTemperature    | mos管温度 |
|    stopTemperature    | mos管温度 |
|     overchargCurr     | 充电电流  |
| hardwareShortCircuitProtection| 输出电流  |
|    abnormalControl    | 太阳能板输出电压  |
*/
void insertEventsOrderRecord(eventsOrderRecordMode mode)
{
    /* 无位置插入时，退出 */
    if (soeInfo.count <= 0 || soeInfo.insertData == NULL) {
        return;
    }

    soeInfo.count--;
    soeInfo.insertData->mode = mode;
    getRTC_Time(&soeInfo.insertData->time);

    if (mode == firstStageProtection) {
        soeInfo.insertData->temp = getDischargCurrent();
    }

    else if (mode == secondStageProtection) {
        soeInfo.insertData->temp = getDischargCurrent();
    }

    else if (mode == thirdStageProtection) {
        soeInfo.insertData->temp = getDischargCurrent();
    }

    else if (mode == lowInputLoad) {
        soeInfo.insertData->temp = getOutputVoltage();
    }

    else if (mode == overTemperature) {
        soeInfo.insertData->temp = getHighSideMosTemperature();
    }

    else if (mode == stopTemperature) {
        soeInfo.insertData->temp = getHighSideMosTemperature();
    }

    else if (mode == overchargCurr) {
        soeInfo.insertData->temp = getChargCurrent();
    }

    else if (mode == overInputVolt) {
        soeInfo.insertData->temp = getSolarInCircuitVoltage();
    }

    else if (mode == hardwareShortCircuitProtection) {
        soeInfo.insertData->temp = getDischargCurrent();
    }
    
    else if (mode == hardwareInputProtection) {
        soeInfo.insertData->temp = get_EXCHG_CURR();
    }

    else if (mode == InputProtection) {
        soeInfo.insertData->temp = get_EXCHG_CURR();
    }

    else if (mode == startEvent) {
        soeInfo.insertData->temp = 0;
    }

    else if (mode == abnormalControl) {
        soeInfo.insertData->temp = getSolarInCircuitVoltage();
    }

    else if (mode == underVoltageProtection) {
        soeInfo.insertData->temp = getBatteryVoltage();
    }

    else {
        soeInfo.count++;
        return;
    }

    soeInfo.insertPos++;
    if (soeInfo.insertPos >= 5) {
        soeInfo.insertPos = 0;
    }

    if (soeInfo.count <= 0) {
        soeInfo.insertData = NULL;
    } else {
        soeInfo.insertData = &soeInfo.data[soeInfo.insertPos];
    }

    soeInfo.outData = &soeInfo.data[soeInfo.outPos];
}


/**
 * @brief  将事件顺序记录在flash中
 * @param
 */
void setEventsOrderRecord(void)
{
    if (soeInfo.outData == NULL || soeInfo.count >= 5) {
        soeInfo.outData = NULL;
        soeInfo.count = 5;
        return;
    }

    // if (soeFlag == 0) {
    //     return;
    // }

    write_Flash((uint8_t *)(soeInfo.outData), soeParameters.pos, soeDataInfoSize);
    // read_Flash((uint8_t *)(soeInfo.outData), eventsOrderRecordStartAddr, sizeof(soeStorageParameters));
        
    // debug_printf("mode = %d \n", soeInfo.outData->mode);
    // debug_printf("year = %d \n", soeInfo.outData->time.year);
    // debug_printf("month = %d \n", soeInfo.outData->time.month);
    // debug_printf("day = %d \n", soeInfo.outData->time.day);
    // debug_printf("hour = %d \n", soeInfo.outData->time.hour);
    // debug_printf("minute = %d \n", soeInfo.outData->time.minute);
    // debug_printf("second = %d \n", soeInfo.outData->time.second);
    
    soeParameters.len++;
    if (soeParameters.len >= 100) {
        soeParameters.len = 0;
        soeParameters.pos = eventsOrderRecordStartAddr + sizeof(soeParameters);
    } else {
        soeParameters.pos += soeDataInfoSize;
    }
    soeParameters.dataLen++;
    write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeStorageParameters));    

    soeInfo.outPos++;
    if (soeInfo.outPos >= 5) {
        soeInfo.outPos = 0;
    }
    soeInfo.count++;

    if (soeInfo.count >= 5) {
        soeInfo.outData = NULL;
    } else {
        soeInfo.outData = &soeInfo.data[soeInfo.outPos];
    }

    if (soeInfo.insertData == NULL) {
        soeInfo.insertData = &soeInfo.data[soeInfo.insertPos];
    }
}

/**
 * @brief   将事件从flash中依次读取出来
 * @param   offset : 距离下次写入数据的偏移量
 *          *data : 数据的储存位置
 */

void readEventsOrderRecord(uint16_t offset, uint8_t *data)
{
    // if (soeFlag == 0) {
    //     return;
    // }

    uint16_t addr;

    if (offset > soeParameters.dataLen) {
        for (size_t i = 0; i < soeDataInfoSize; i++) {
            data[i] = 0;
        }

        return;
    }

    if (soeParameters.len - offset < 0) {
        addr = eventsOrderRecordStartAddr + sizeof(soeStorageParameters)
         + (100 + soeParameters.len - offset) * soeDataInfoSize;
    } else {
        addr = eventsOrderRecordStartAddr + sizeof(soeStorageParameters)
         + (soeParameters.len - offset) * soeDataInfoSize;
    }
    
    read_Flash(data, addr, soeDataInfoSize);
}


/**
 * @brief   清除SOE所有事件
 * @param   
 */
void cleanEventsOrderRecord(void)
{
    // soeFlag = 0;
    // erase_Sector_Flash((eventsOrderRecordStartAddr / 4096));

    soeParameters.len = 0;
    soeParameters.dataLen = 0;
    soeParameters.pos = eventsOrderRecordStartAddr + sizeof(soeParameters);
    write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters));
    
    // TimeSliceOffset_Register(&g_SOE_flag, Task_SOE_flag, uart_reloadVal, uart_offset); 
}

// extern STR_TimeSliceOffset g_SOE_flag;
// void Task_SOE_flag(void)
// {        
//     soeParameters.len = 0;
//     soeParameters.pos = eventsOrderRecordStartAddr + sizeof(soeParameters);
//     write_Flash((uint8_t *)(&soeParameters), eventsOrderRecordStartAddr, sizeof(soeParameters));
    
//     soeFlag = 1;


// }