/*
 * 自然写智能点阵笔嵌入式固件软件 V1.0
 * power_manager.c - 电源管理模块
 *
 * 功能说明：
 * 1. 低功耗状态机管理（Active/LightSleep/DeepSleep）
 * 2. 各外设电源域控制
 * 3. 唤醒源配置与管理
 * 4. 功耗统计与优化
 */

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "hal_gpio.h"
#include "hal_rtc.h"

/* ========== 电源域定义 ========== */

#define POWER_DOMAIN_CAMERA     (1 << 0)   /* 摄像头 */
#define POWER_DOMAIN_BLE        (1 << 1)   /* BLE模块 */
#define POWER_DOMAIN_FLASH      (1 << 2)   /* 外部Flash */
#define POWER_DOMAIN_SENSOR     (1 << 3)   /* 压力传感器 */
#define POWER_DOMAIN_LED        (1 << 4)   /* LED指示灯 */
#define POWER_DOMAIN_ALL        0xFF

/* ========== 唤醒源定义 ========== */

#define WAKEUP_SRC_PEN_TIP      (1 << 0)   /* 笔尖接触 */
#define WAKEUP_SRC_BUTTON       (1 << 1)   /* 按键 */
#define WAKEUP_SRC_CHARGER      (1 << 2)   /* 充电器插入 */
#define WAKEUP_SRC_RTC          (1 << 3)   /* RTC定时唤醒 */
#define WAKEUP_SRC_BLE          (1 << 4)   /* BLE连接事件 */

/* ========== 功耗模式参数 ========== */

/* 轻度睡眠时的CPU频率（MHz） */
#define LIGHT_SLEEP_FREQ_MHZ    16

/* 正常工作CPU频率（MHz） */
#define ACTIVE_FREQ_MHZ         168

/* RTC唤醒间隔（秒） - 用于周期性电量检查 */
#define RTC_WAKEUP_INTERVAL_S   60

/* ========== 静态变量 ========== */

/* 当前活跃的电源域 */
static uint8_t s_active_domains = POWER_DOMAIN_ALL;

/* 当前唤醒源配置 */
static uint8_t s_wakeup_sources = 0;

/* 功耗统计 */
static uint32_t s_active_time_ms = 0;
static uint32_t s_sleep_time_ms = 0;

/* ========== 电源管理初始化 ========== */

/**
 * 初始化电源管理模块
 * 配置各电源域控制GPIO，设置默认唤醒源
 */
void power_manager_init(void) {
    /* 配置电源控制GPIO */
    hal_gpio_config_output(GPIO_CAMERA_POWER);
    hal_gpio_config_output(GPIO_FLASH_POWER);
    hal_gpio_config_output(GPIO_SENSOR_POWER);
    hal_gpio_config_output(GPIO_LED_POWER);

    /* 默认所有电源域开启 */
    s_active_domains = POWER_DOMAIN_ALL;

    /* 默认唤醒源：笔尖触摸 + 充电器 + 按键 */
    s_wakeup_sources = WAKEUP_SRC_PEN_TIP | WAKEUP_SRC_CHARGER | WAKEUP_SRC_BUTTON;

    /* 初始化功耗统计 */
    s_active_time_ms = 0;
    s_sleep_time_ms = 0;
}

/* ========== 电源域控制 ========== */

/**
 * 使能指定电源域
 * @param domain_mask  电源域掩码
 */
void power_domain_enable(uint8_t domain_mask) {
    if (domain_mask & POWER_DOMAIN_CAMERA) {
        hal_gpio_write(GPIO_CAMERA_POWER, 1);
    }
    if (domain_mask & POWER_DOMAIN_FLASH) {
        hal_gpio_write(GPIO_FLASH_POWER, 1);
    }
    if (domain_mask & POWER_DOMAIN_SENSOR) {
        hal_gpio_write(GPIO_SENSOR_POWER, 1);
    }
    if (domain_mask & POWER_DOMAIN_LED) {
        hal_gpio_write(GPIO_LED_POWER, 1);
    }

    s_active_domains |= domain_mask;
}

/**
 * 禁用指定电源域
 * @param domain_mask  电源域掩码
 */
void power_domain_disable(uint8_t domain_mask) {
    if (domain_mask & POWER_DOMAIN_CAMERA) {
        hal_gpio_write(GPIO_CAMERA_POWER, 0);
    }
    if (domain_mask & POWER_DOMAIN_FLASH) {
        hal_gpio_write(GPIO_FLASH_POWER, 0);
    }
    if (domain_mask & POWER_DOMAIN_SENSOR) {
        hal_gpio_write(GPIO_SENSOR_POWER, 0);
    }
    if (domain_mask & POWER_DOMAIN_LED) {
        hal_gpio_write(GPIO_LED_POWER, 0);
    }

    s_active_domains &= ~domain_mask;
}

/* ========== 低功耗状态转换 ========== */

/**
 * 进入轻度睡眠模式
 * - 降低CPU频率到16MHz
 * - 关闭摄像头和传感器电源域
 * - 保持BLE连接和Flash电源
 * - 可由笔尖触摸或BLE事件唤醒
 */
void power_enter_light_sleep(void) {
    /* 关闭不必要的电源域 */
    power_domain_disable(POWER_DOMAIN_CAMERA | POWER_DOMAIN_SENSOR | POWER_DOMAIN_LED);

    /* 降低CPU频率 */
    SystemClock_SetFrequency(LIGHT_SLEEP_FREQ_MHZ);

    /* 配置唤醒源 */
    hal_gpio_set_wakeup(GPIO_PEN_TIP_PIN, GPIO_WAKEUP_RISING);
    hal_gpio_set_wakeup(GPIO_BUTTON_PIN, GPIO_WAKEUP_FALLING);

    /* 进入CPU SLEEP模式（WFI等待中断） */
    __WFI();

    /* 唤醒后恢复 */
    SystemClock_SetFrequency(ACTIVE_FREQ_MHZ);
    power_domain_enable(POWER_DOMAIN_SENSOR | POWER_DOMAIN_LED);
}

/**
 * 进入深度睡眠模式
 * - 关闭所有外设电源域
 * - 断开BLE连接
 * - MCU进入STOP/STANDBY模式
 * - 仅保留RTC和GPIO唤醒
 * - 唤醒后相当于系统复位重启
 */
void power_enter_deep_sleep(void) {
    /* 保存关键数据到Flash */
    save_power_state();

    /* 关闭所有电源域 */
    power_domain_disable(POWER_DOMAIN_ALL);

    /* 配置RTC唤醒（定时检查电量） */
    hal_rtc_set_alarm(RTC_WAKEUP_INTERVAL_S);

    /* 配置GPIO唤醒源 */
    hal_gpio_set_wakeup(GPIO_PEN_TIP_PIN, GPIO_WAKEUP_RISING);
    hal_gpio_set_wakeup(GPIO_USB_DETECT_PIN, GPIO_WAKEUP_RISING);
    hal_gpio_set_wakeup(GPIO_BUTTON_PIN, GPIO_WAKEUP_FALLING);

    /* 进入STANDBY模式（最低功耗，唤醒后从头执行） */
    hal_enter_standby_mode();
}

/* ========== 功耗状态保存/恢复 ========== */

/* Flash中保存电源状态的地址 */
#define POWER_STATE_FLASH_ADDR  0x0000F000

/* 电源状态保存结构 */
typedef struct {
    uint32_t magic;                 /* 魔数 0xPWR55AA */
    uint32_t total_active_ms;       /* 累计活跃时长 */
    uint32_t total_sleep_ms;        /* 累计睡眠时长 */
    uint32_t boot_count;            /* 启动次数 */
    uint32_t last_shutdown_reason;  /* 上次关机原因 */
    uint32_t checksum;              /* CRC校验 */
} PowerStateFlash;

/**
 * 保存电源状态到Flash
 * 在进入深度睡眠前调用
 */
static void save_power_state(void) {
    PowerStateFlash state;
    state.magic = 0x50575200;  /* "PWR\0" */
    state.total_active_ms = s_active_time_ms;
    state.total_sleep_ms = s_sleep_time_ms;
    state.boot_count = 0;  /* 将在恢复时递增 */
    state.last_shutdown_reason = 0;

    /* 计算校验和 */
    uint32_t sum = 0;
    const uint32_t *data = (const uint32_t *)&state;
    uint8_t i;
    for (i = 0; i < (sizeof(state) / 4) - 1; i++) {
        sum ^= data[i];
    }
    state.checksum = sum;

    /* 写入Flash */
    hal_flash_erase_sector(POWER_STATE_FLASH_ADDR);
    hal_flash_write(POWER_STATE_FLASH_ADDR, (const uint8_t *)&state, sizeof(state));
}

/**
 * 从Flash恢复电源状态
 * 在启动时调用
 */
void power_restore_state(void) {
    PowerStateFlash state;
    hal_flash_read(POWER_STATE_FLASH_ADDR, (uint8_t *)&state, sizeof(state));

    if (state.magic != 0x50575200) {
        /* 无有效的保存数据 */
        return;
    }

    /* 验证校验和 */
    uint32_t sum = 0;
    const uint32_t *data = (const uint32_t *)&state;
    uint8_t i;
    for (i = 0; i < (sizeof(state) / 4) - 1; i++) {
        sum ^= data[i];
    }

    if (sum != state.checksum) {
        return;  /* 数据损坏 */
    }

    /* 恢复功耗统计 */
    s_active_time_ms = state.total_active_ms;
    s_sleep_time_ms = state.total_sleep_ms;
}

/* ========== 功耗统计接口 ========== */

/**
 * 更新活跃时间统计
 * @param elapsed_ms  经过的毫秒数
 */
void power_update_active_time(uint32_t elapsed_ms) {
    s_active_time_ms += elapsed_ms;
}

/**
 * 更新睡眠时间统计
 * @param elapsed_ms  经过的毫秒数
 */
void power_update_sleep_time(uint32_t elapsed_ms) {
    s_sleep_time_ms += elapsed_ms;
}

/**
 * 获取累计活跃时长（秒）
 */
uint32_t power_get_active_seconds(void) {
    return s_active_time_ms / 1000;
}

/**
 * 获取电源效率（活跃时间占比百分比）
 */
uint8_t power_get_efficiency(void) {
    uint32_t total = s_active_time_ms + s_sleep_time_ms;
    if (total == 0) return 100;
    return (uint8_t)((uint64_t)s_active_time_ms * 100 / total);
}

/**
 * 获取当前活跃的电源域掩码
 */
uint8_t power_get_active_domains(void) {
    return s_active_domains;
}
