#include "ota_message.h"
#include "gd32f10x.h"
#include "w25q32.h"
#include "ec800m.h"
#include "usart.h"
#include "delay.h"
#include <stdio.h>

static OTA_MESSAGE ota_message = {0};
void clear_ota_message_config_block(void);
void write_ota_message_to_flash(uint32_t *data, int size){
	uint8_t *pdata = (uint8_t *)data;
	W25Q32_PageWrite(pdata,256*OTA_EVENT_BLOCK);//写在第二扇区的第一页中
}

/*
 *  函数名：save_ota_message_config_params(OTA_MESSAGE *params)
 *  输入参数：无
 *  输出参数：无
 *  返回值：无
 *  函数作用：保存ota事件的信息
 */
int save_ota_message_config_params(OTA_MESSAGE *params)
{
		if(params == NULL)
				return -1;
		memset(&ota_message, 0, sizeof(OTA_MESSAGE));	
		memcpy(&ota_message, params, sizeof(OTA_MESSAGE)); 
	  clear_ota_message_config_block();
		write_ota_message_to_flash((uint32_t *)&ota_message,sizeof(OTA_MESSAGE));
		return 0;
}

// 模块下载download校验值
static uint16_t checksum(const char *str, uint16_t len)
{
  uint16_t sum = 0;
  uint8_t odd = 0;

  // 如果字符串长度为奇数，则将最后一个字符设置为高8位，低8位设置为0
  if (len % 2 == 1)
  {
    odd = 1;
    len--;
  }

  // 将每两个字符作为一个16位的数值进行异或操作
  for (uint16_t i = 0; i < len; i += 2)
  {
    sum ^= ((uint16_t)str[i] << 8) | (uint16_t)str[i + 1];
  }

  // 如果字符串长度为奇数，则还需要将最后一个字符与0xFF00异或
  if (odd)
  {
    sum ^= (uint16_t)str[len] << 8;
  }
  // 返回校验和
  return sum;
}

//返回str在数组中的索引
static char* find_string(char *strs, char *str, int len)
{
    int i = 0;
	char *start = NULL;
    while(i < len){
		start = strstr(strs, str);
        if(start != NULL){
            break;
        }
        i++;
        strs++;
    }
    if(i == len + 1){
        return NULL;
    }
    return start;
}


/*
 *  函数名：static void extract_data_from_buffer(const char* buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr)
 *  输入参数：buffer字符串
 *  输出参数：json有效字符串长度len_ptr,checkCode_ptr校验码指针
 *  返回值：无
 *  函数作用:eg.   QFDWL: 621,3e23  从json信息最后端取出这段json的有效长度和校验码
 */
static void extract_data_from_buffer(char* buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr)
{
  char *start = find_string(buffer, "+QFDWL:",128);
  if (start != NULL)
  {
    start += 8; // 跳过"+QFDWL:"
    uint32_t len = 0;
    sscanf(start, "%u,", &len);     // 读取长度
    start = strchr(start, ',') + 1; // 跳过逗号
    uint16_t checkCode = 0;
    sscanf(start, "%hx", &checkCode); // 读取16进制数据
    // 将提取的数据存入形参
    *len_ptr = len;
    *checkCode_ptr = checkCode;
  }
}

bool WaitForUpData(char* dmaBuffer)
{
	if (UART0_RX_STAT > 0)
  	{
		UART0_RX_STAT = 0;
		uint32_t len;
		uint16_t checkCode;
			char *temp;
		extract_data_from_buffer(dmaBuffer, &len, &checkCode);
		uint16_t jsonCheck = checksum(dmaBuffer, len);
		if (checkCode == jsonCheck)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}

/*
 *  函数名：load_config_params(CONFIG_PARAMS *params)
 *  输入参数：无
 *  输出参数：无
 *  返回值：ota升级标志是否有效 0有效 -1无效
 *  函数作用：从w25q32中加载ota信息
 */
int load_ota_message_config_params()
{
	//检查校验码
	uint8_t BufferSize = 128;		//最大获取的数据空间
	char dmabuffer[BufferSize];
	__LOAD_CONFIG:
	// get data from UFS
	memset(dmabuffer,0,BufferSize);
	dma_config_change(dmabuffer,BufferSize);
	Delay_Ms(1000);
	EC800MSendCmd(LOAD_otaMSG_FILE, strlen(LOAD_otaMSG_FILE)); //"AT+QFDWL=otaMSG.txt\r\n"
	Delay_Ms(1000);
	dma_config();
	if(WaitForUpData(dmabuffer) == false) goto __LOAD_CONFIG;
	// W25Q32_Read((uint8_t *)&ota_message, OTA_EVENT_BLOCK*64*1024, sizeof(OTA_MESSAGE)); //从W25Q32中读取结构体数据
	// FLASH_Read(OTA_EVENT_START_ADDR,&ota_message,sizeof(OTA_MESSAGE));
	memset(&ota_message,0,sizeof(OTA_MESSAGE));
	memcpy((uint8_t*)&ota_message,dmabuffer,sizeof(OTA_MESSAGE));
	free(dmabuffer);
	if(ota_message.otaflag == 1U)
	{
		
		return 0;
	}
	else 
	{
		return -1;
	}
}
OTA_MESSAGE *get_config_params()
{
		return &ota_message;
}
/*
 *  函数名：void clear_ota_message_config_block(void)
 *  输入参数：无
 *  输出参数：无
 *  返回值：无
 *  函数作用：清除ota事件信息
 */
void clear_ota_message_config_block(void)
{
	static OTA_MESSAGE ota_message = {0};
	
	while(1)
	{
		EC800MSendCmd(OPEN_otaMSG_FILE,strlen(OPEN_otaMSG_FILE));
		if(WaitResponse("QFOPEN:", 2000))
			break;
	}
	while(1)
	{
		EC800MSendCmd(WRITE_otaMSG_FILE,strlen(WRITE_otaMSG_FILE));
		if(WaitResponse("CONNECT", 2000))
			break;
	}
	while (1)
	{
		EC800MSendCmd((uint8_t *)&ota_message,sizeof(OTA_MESSAGE));
		if(WaitResponse("QFWRITE", 5000))
			break;
	}
	while (1)
	{
		EC800MSendCmd(CLOSE_otaMSG_FILE,strlen(CLOSE_otaMSG_FILE));
		if(WaitResponse("OK", 2000))
			break;
	}

	// EC800MSendCmd("AT+QFDEL=\"UFS:otaMSG.txt\r\n\"",27);	//删除文件
}
