#include "parameter.h"
#include <stdio.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "string.h"
#include "esp_log.h"
#include "flash_drv.h"

const char* flash_system_data_tag = FLASH_SYSTEM_DATA_TAG;
const char* flash_system_work_data_key = FLASH_SYSTEM_WORK_DATA_KEY;

nvs_handle_t flash_system_data_handle;
uint8_t flash_hd_error = 0;

static const char *FLASH_TAG = "FLASH_DRV";

/**
 * 模块名: FlashInit
 * 代码描述: Flash初始化
 * 作者: luo
 * 创建时间: 2024/05/07 09:56:34
 */
void FlashInit(void)  // Flash初始化，超过3次则认为硬件损害
{
    uint8_t init_num = 3;
    esp_err_t err = nvs_flash_init();  // 初始化
    ESP_LOGI(FLASH_TAG, "NVS初始化，返回值: %d", err);
    while (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_LOGW(FLASH_TAG, "NVS初始化失败: %s，需要擦除分区并重试，剩余重试次数: %d", esp_err_to_name(err), init_num);
        if(init_num == 0)
        {
            flash_hd_error = 1;
            ESP_LOGE(FLASH_TAG, "NVS初始化连续失败，Flash硬件可能损坏！");
            return;
        }
        init_num --;
        ESP_LOGI(FLASH_TAG, "擦除NVS分区...");
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
        ESP_LOGI(FLASH_TAG, "NVS重新初始化，返回值: %d", err);
    }
    if (err == ESP_OK) {
        ESP_LOGI(FLASH_TAG, "NVS初始化成功");
    } else {
        flash_hd_error = 1;
        ESP_LOGE(FLASH_TAG, "NVS初始化失败，错误码: %d", err);
    }
}

/**
 * 模块名: FlashSystemWorkParameterWrite
 * 代码描述: 工作参数存储
 * 作者: luo
 * 创建时间: 2024/05/07 09:54:25
 */
void FlashSystemWorkParameterWrite(system_work_parameter_struct *current_data)  
{
    // 需要创建一个读取写入数据的变量，用于比较是否写入正确
    uint8_t init_num = 3;
    system_work_parameter_struct read_flash_data;
    system_work_parameter_struct write_flash_data;
    size_t length = sizeof(system_work_parameter_struct);
    memset(&read_flash_data, 0, length);
    memcpy(&write_flash_data, current_data, sizeof(system_work_parameter_struct));
    if(flash_hd_error == 1)
    {
        return;
    }
    while(init_num)
    {
        init_num --;
        nvs_open(flash_system_data_tag, NVS_READWRITE, &flash_system_data_handle);  // 打开空间，操作为读和写，句柄
        nvs_set_blob(flash_system_data_handle, flash_system_work_data_key, &write_flash_data, length);  // 数据写入
        nvs_commit(flash_system_data_handle);  // 需要读取出来后查看数据是否正确
        nvs_get_blob(flash_system_data_handle, flash_system_work_data_key, &read_flash_data, &length);
        nvs_close(flash_system_data_handle);
        if(memcmp(&write_flash_data, &read_flash_data, length) != 0)
        {
            if(init_num == 0)
            {
                flash_hd_error = 1;
            }
        }
        else
        {
            memcpy(current_data, &read_flash_data, sizeof(system_work_parameter_struct));
            break;
        }
    }
}

/**
 * 模块名: FlashSystemWorkParameterRead
 * 代码描述: 读取工作参数
 * 作者: luo
 * 创建时间: 2024/05/07 09:53:47
 */
uint8_t FlashSystemWorkParameterRead(system_work_parameter_struct *data)
{
    system_work_parameter_struct read_flash_data;
    size_t length = sizeof(system_work_parameter_struct);
    nvs_open(flash_system_data_tag, NVS_READWRITE, &flash_system_data_handle);  // 打开空间，操作为读和写，句柄
    nvs_get_blob(flash_system_data_handle, flash_system_work_data_key, &read_flash_data, &length);
    nvs_close(flash_system_data_handle);
    if(read_flash_data.flash_save_flag != 0x5a5a)  // 非第一次写入数据
    {
        return 0;
    }
    memcpy(data, &read_flash_data, length);
    return 1;
} 