#ifndef POWER_MGMT_H
#define POWER_MGMT_H

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

/*
 * power_mgmt — STM32F7 STOP-mode sleep/wake manager (Issue #178).
 *
 * State machine:
 *   PM_ACTIVE ──(idle ≥ PM_IDLE_TIMEOUT_MS or sleep cmd)──► PM_SLEEP_PENDING
 *   PM_SLEEP_PENDING ──(fade complete, ≥ PM_FADE_MS)──► PM_SLEEPING (WFI)
 *   PM_SLEEPING ──(EXTI wake)──► PM_WAKING ──(clocks restored)──► PM_ACTIVE
 *
 *   Any call to power_mgmt_activity() during SLEEP_PENDING or SLEEPING
 *   immediately transitions back toward PM_ACTIVE.
 *
 * Wake sources (EXTI, falling edge on UART idle-high RX pin or IMU INT):
 *   EXTI1  PA1  UART4_RX   — CRSF/ELRS start bit
 *   EXTI7  PB7  USART1_RX  — JLink start bit
 *   EXTI4  PC4  MPU6000 INT — IMU motion (handler owned by mpu6000.c)
 *
 * Peripheral gating on sleep entry (clock disable, state preserved):
 *   Disabled: SPI3/I2S3 (audio amp), SPI2 (OSD), USART6, UART5 (debug)
 *   Active:   SPI1 (IMU), UART4 (CRSF), USART1 (JLink), I2C1 (baro/mag)
 *
 * Sleep LED (LED1, active-low PC15):
 *   PM_SLEEP_PENDING: triangle-wave pulse, period PM_LED_PERIOD_MS
 *   All other states: 0 (caller uses normal LED logic)
 *
 * IWDG:
 *   Fed immediately before WFI. STOP wakeup <10 ms typical — well within
 *   WATCHDOG_TIMEOUT_MS (50 ms).
 *
 * Safety interlock:
 *   Caller MUST NOT call power_mgmt_tick() while armed; call
 *   power_mgmt_activity() instead to keep the idle timer reset.
 *
 * JLink integration:
 *   JLINK_CMD_SLEEP (0x09) → power_mgmt_request_sleep()
 *   Any valid JLink frame → power_mgmt_activity()  (handled in main loop)
 */

typedef enum {
    PM_ACTIVE        = 0,  /* Normal, all peripherals running */
    PM_SLEEP_PENDING = 1,  /* Idle timeout reached; LED fade-out in progress */
    PM_SLEEPING      = 2,  /* In STOP mode (WFI); execution blocked in tick() */
    PM_WAKING        = 3,  /* Transitional; clocks/peripherals being restored */
} PowerState;

/* ---- API ---- */

/*
 * power_mgmt_init() — configure wake EXTI lines (EXTI1, EXTI7).
 * Call after crsf_init() and jlink_init().
 */
void power_mgmt_init(void);

/*
 * power_mgmt_activity() — record cmd_vel event (CRSF frame, JLink frame).
 * Resets idle timer; aborts any pending/active sleep.
 */
void power_mgmt_activity(void);

/*
 * power_mgmt_request_sleep() — force sleep regardless of idle timer
 * (called on JLINK_CMD_SLEEP). Next tick() enters PM_SLEEP_PENDING.
 */
void power_mgmt_request_sleep(void);

/*
 * power_mgmt_tick(now_ms) — drive state machine. May block in WFI during
 * STOP mode. Returns state after this tick.
 * MUST NOT be called while balance_state == BALANCE_ARMED.
 */
PowerState power_mgmt_tick(uint32_t now_ms);

/* power_mgmt_state() — non-blocking read of current state. */
PowerState power_mgmt_state(void);

/*
 * power_mgmt_led_brightness() — 0-255 brightness for sleep-pending pulse.
 * Returns 0 when not in PM_SLEEP_PENDING; caller uses normal LED logic.
 */
uint8_t power_mgmt_led_brightness(void);

/*
 * power_mgmt_current_ma() — estimated total current draw (mA) based on
 * gating state; populated in JLINK_TLM_POWER telemetry.
 */
uint16_t power_mgmt_current_ma(void);

/* power_mgmt_idle_ms() — ms elapsed since last power_mgmt_activity() call. */
uint32_t power_mgmt_idle_ms(void);

/*
 * power_mgmt_notify_battery(vbat_mv) — Issue #467 integration.
 * Called by battery_adc_check_pm() after BATTERY_ADC_LOW_HOLD_MS of sustained
 * critical voltage.  Forces PM_SLEEP_PENDING to protect the LiPo.
 */
void power_mgmt_notify_battery(uint32_t vbat_mv);

#endif /* POWER_MGMT_H */
