#include "performance_monitor.h"
#include <string.h>
#include <stdlib.h>

// 静态变量
static SystemPerfStats_t g_perf_stats = {0};
static uint32_t g_task_start_time[PERF_MON_MAX_TASKS] = {0};
static uint8_t g_task_active[PERF_MON_MAX_TASKS] = {0};

// 外部符号声明 (用于堆栈监控)
extern uint32_t _estack;
extern uint32_t _Min_Stack_Size;

/**
  * @brief 初始化性能监控模块
  * @param None
  * @retval None
  */
void PerformanceMonitor_Init(void)
{
    memset(&g_perf_stats, 0, sizeof(SystemPerfStats_t));
    memset(g_task_start_time, 0, sizeof(g_task_start_time));
    memset(g_task_active, 0, sizeof(g_task_active));
    
    g_perf_stats.sample_period_ms = PERF_MON_SAMPLE_PERIOD_MS;
    g_perf_stats.last_update_tick = HAL_GetTick();
    
    // 初始化最小执行时间为最大值
    for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
        g_perf_stats.tasks[i].min_time_us = UINT32_MAX;
    }
    
}
    
/**
  * @brief 开始任务性能监控
  * @param task_id: 任务ID
  * @retval None
  */
void PerformanceMonitor_TaskStart(PerfTaskID_t task_id)
{
    if (task_id >= PERF_MON_MAX_TASKS) return;
    
    g_task_start_time[task_id] = HAL_GetTick() * 1000; // 转换为微秒
    g_task_active[task_id] = 1;
}

/**
  * @brief 结束任务性能监控
  * @param task_id: 任务ID
  * @retval None
  */
void PerformanceMonitor_TaskEnd(PerfTaskID_t task_id)
{
    if (task_id >= PERF_MON_MAX_TASKS || !g_task_active[task_id]) return;
    
    uint32_t end_time = HAL_GetTick() * 1000; // 转换为微秒
    uint32_t execution_time = end_time - g_task_start_time[task_id];
    
    TaskPerfStats_t *task_stats = &g_perf_stats.tasks[task_id];
    
    // 更新统计信息
    task_stats->total_time_us += execution_time;
    task_stats->call_count++;
    
    // 更新最大最小时间
    if (execution_time > task_stats->max_time_us) {
        task_stats->max_time_us = execution_time;
    }
    if (execution_time < task_stats->min_time_us) {
        task_stats->min_time_us = execution_time;
    }
    
    // 计算平均时间
    task_stats->avg_time_us = task_stats->total_time_us / task_stats->call_count;
    
    g_task_active[task_id] = 0;
}

/**
  * @brief 更新性能监控统计
  * @param None
  * @retval None
  */
void PerformanceMonitor_Update(void)
{
    uint32_t current_tick = HAL_GetTick();
    
    // 检查是否到了更新周期
    if (current_tick - g_perf_stats.last_update_tick < g_perf_stats.sample_period_ms) {
        return;
    }
    
    // 计算CPU使用率
    uint32_t total_cpu_time = 0;
    for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
        if (g_perf_stats.tasks[i].call_count > 0) {
            // 计算每个任务的CPU使用率
            uint32_t task_time_per_period = g_perf_stats.tasks[i].avg_time_us *
                                           (1000 / g_perf_stats.sample_period_ms);
            g_perf_stats.tasks[i].cpu_usage_percent =
                (float)task_time_per_period / 10000.0f; // 转换为百分比
            
            total_cpu_time += task_time_per_period;
        }
    }
    
    // 更新总CPU使用率
    g_perf_stats.total_cpu_usage_percent = total_cpu_time / 100;
    
    // 更新内存使用情况
    g_perf_stats.free_heap_size = PerformanceMonitor_GetFreeHeapSize();
    if (g_perf_stats.min_free_heap_size == 0 ||
        g_perf_stats.free_heap_size < g_perf_stats.min_free_heap_size) {
        g_perf_stats.min_free_heap_size = g_perf_stats.free_heap_size;
    }
    
    // 更新栈使用率
    g_perf_stats.stack_usage_percent = PerformanceMonitor_GetStackUsage();
    
    g_perf_stats.last_update_tick = current_tick;
}

/**
  * @brief 获取性能统计信息
  * @param stats: 统计信息结构体指针
  * @retval None
  */
void PerformanceMonitor_GetStats(SystemPerfStats_t *stats)
{
    if (stats != NULL) {
        memcpy(stats, &g_perf_stats, sizeof(SystemPerfStats_t));
    }
}

/**
  * @brief 重置性能统计
  * @param None
  * @retval None
  */
void PerformanceMonitor_ResetStats(void)
{
    memset(&g_perf_stats, 0, sizeof(SystemPerfStats_t));
    g_perf_stats.sample_period_ms = PERF_MON_SAMPLE_PERIOD_MS;
    g_perf_stats.last_update_tick = HAL_GetTick();
    
    // 重新初始化最小执行时间
    for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
        g_perf_stats.tasks[i].min_time_us = UINT32_MAX;
    }
}

/**
  * @brief 获取空闲堆内存大小
  * @param None
  * @retval 空闲堆内存大小(字节)
  */
uint32_t PerformanceMonitor_GetFreeHeapSize(void)
{
    // 简单的堆内存检测方法
    // 在实际应用中，可能需要更复杂的内存管理
    void *ptr = malloc(1);
    if (ptr != NULL) {
        free(ptr);
        // 这里返回一个估算值，实际项目中需要更精确的实现
        return 32768; // 假设有32KB空闲堆内存
    }
    return 0;
}

/**
  * @brief 获取栈使用率
  * @param None
  * @retval 栈使用率百分比
  */
uint32_t PerformanceMonitor_GetStackUsage(void)
{
    // 获取当前栈指针
    uint32_t current_sp;
    __asm volatile ("mov %0, sp" : "=r" (current_sp));
    
    // 计算栈使用量
    uint32_t stack_top = (uint32_t)&_estack;
    uint32_t min_stack_size = (uint32_t)&_Min_Stack_Size;
    uint32_t stack_used = stack_top - current_sp;
    
    // 计算使用率百分比
    if (min_stack_size > 0) {
        return (stack_used * 100) / min_stack_size;
    }
    
    return 0;
}