/**
 * @file httpsOTA.c
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2026-10-23
 * 
 * @copyright Copyright (c) 2026
 * 
 */


#include "httpsOTA.h"

#define TAG "Ota"


static TaskHandle_t OtaTaskHandle = NULL;


/* 用于捕获系统事件的事件处理程序 */
static void event_handler(void *arg, esp_event_base_t event_base,int32_t event_id, void *event_data){
  if (event_base == ESP_HTTPS_OTA_EVENT){
    switch (event_id){
      case ESP_HTTPS_OTA_START:
        ESP_LOGI(TAG, "OTA 已开始");
        break;
      case ESP_HTTPS_OTA_CONNECTED:
        ESP_LOGI(TAG, "已连接到服务器");
        break;
      case ESP_HTTPS_OTA_GET_IMG_DESC:
        ESP_LOGI(TAG, "阅读图像描述");
        break;
      case ESP_HTTPS_OTA_VERIFY_CHIP_ID:
        ESP_LOGI(TAG, "验证新镜像的芯片 ID: %d", *(esp_chip_id_t *)event_data);
        break;
      case ESP_HTTPS_OTA_VERIFY_CHIP_REVISION:
        ESP_LOGI(TAG, "正在验证新镜像的芯片版本: %d", *(uint16_t *)event_data);
        break;
      case ESP_HTTPS_OTA_DECRYPT_CB:
        ESP_LOGI(TAG, "解密函数的回调");
        break;
      case ESP_HTTPS_OTA_WRITE_FLASH:
        ESP_LOGD(TAG, "写入闪存: %d written", *(int *)event_data);
        break;
      case ESP_HTTPS_OTA_UPDATE_BOOT_PARTITION:
        ESP_LOGI(TAG, "引导分区已更新。下一个分区: %d", *(esp_partition_subtype_t *)event_data);
        break;
      case ESP_HTTPS_OTA_FINISH:
        ESP_LOGI(TAG, "OTA 完成");
        break;
      case ESP_HTTPS_OTA_ABORT:
        ESP_LOGI(TAG, "OTA终止");
        break;
    }
  }
}


static char *OtaUrl = NULL;

//OTA 进度 -1~100 -1为没有OTA 
static int OtaProgress = -1;


static void OtaTask(void *arg){
  OtaCallback OtaCallbackFn = (OtaCallback)arg;
  ESP_LOGI(TAG,"OtaUrl= %s",OtaUrl);
  // 注册你的处理函数,监听 ESP_HTTPS_OTA_EVENT 事件基
  esp_event_handler_register(ESP_HTTPS_OTA_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);
  esp_http_client_config_t httpCfg = {
    .url = OtaUrl,
    .crt_bundle_attach = esp_crt_bundle_attach,
  };
  esp_https_ota_config_t otaCfg = {
    .http_config = &httpCfg,
  };
  esp_https_ota_handle_t httpsOtaHandle;
  if(esp_https_ota_begin(&otaCfg,&httpsOtaHandle) == ESP_OK){
    if(httpsOtaHandle != NULL){
      int otaImageSize = esp_https_ota_get_image_size(httpsOtaHandle);
      ESP_LOGI(TAG,"要下载的OTA镜像有 %d bytes",otaImageSize);
  
      while(esp_https_ota_perform(httpsOtaHandle) == ESP_ERR_HTTPS_OTA_IN_PROGRESS){
        int otaGetImageSize = esp_https_ota_get_image_len_read(httpsOtaHandle);
        //ESP_LOGI(TAG,"已下载的OTA大小 %d bytes",otaGetImageSize);
        OtaProgress = (int)((float)otaGetImageSize/(float)otaImageSize*100);
        OtaCallbackFn(otaImageSize,otaGetImageSize,OtaProgress);
      }
      
      if(esp_https_ota_is_complete_data_received(httpsOtaHandle) == true){
        OtaCallbackFn(otaImageSize,otaImageSize,100);
        esp_https_ota_finish(httpsOtaHandle);
        esp_restart();
      }else{
        OtaCallbackFn(otaImageSize,otaImageSize,-1);
        esp_https_ota_abort(httpsOtaHandle);
      }
    }
  }else{
    OtaCallbackFn(0,0,-1);
  }

  OtaProgress = -1;
  free(OtaUrl);
  esp_event_handler_unregister(ESP_HTTPS_OTA_EVENT, ESP_EVENT_ANY_ID, &event_handler);
  ESP_LOGE(TAG,"OTA 升级任务结束");
  OtaTaskHandle = NULL;
  vTaskDelete(OtaTaskHandle);
}


/**
 * @brief 启动 https OTA 升级任务
 * 
 * @param Url 
 */
void OtaStart(char *Url,OtaCallback OtaCallbackFn){
  if(OtaTaskHandle == NULL){
    OtaUrl = (char *)malloc(strlen(Url)+1);
    if(OtaUrl != NULL){
      memset(OtaUrl,0,strlen(Url)+1);
      strcpy(OtaUrl,Url);
      xTaskCreate(OtaTask,"OtaTask",4096,OtaCallbackFn,0,&OtaTaskHandle);
    }
  }
}

//读取 OTA 进度
int GetOtaProgress(){
  return OtaProgress;
}