#include "app_leakage.h"

#include <string.h>
#include "bsp_w25q.h"
#include "bsp_buzzer.h"
#include "bsp_relay.h"
#include "bsp_DS1302.h"

static void history_clear_all(void);
static u8 history_read_record(u32 record_index, app_leakage_history_alarm_t *record);
static void history_init(void);
static void history_save_metadata(void);

static void app_leakage_init(void);

/*历史报警缓冲区*/
uint8_t sector_buf[2][W25Q32_SECTOR_SIZE];

app_leakage_t leakage =
    {
        .region_num = 0,
        .sub_device_num = 0,
        .init = app_leakage_init,
        .task = app_leakage_task,
        .class_update = app_leakage_region_classify,
};
app_leakage_t *p_leakage = &leakage;

app_hitory_t history =
    {
        .read_history = history_read_record,
        .clean_history = history_clear_all,
        .init_history = history_init};

static void app_leakage_init(void)
{
    //   for(int i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++)
    //   {
    //      memset(leakage.sub_device_data[i].ch_data, 0,
    //             sizeof(leakage.sub_device_data[i].ch_data));
    //   }
    app_leakage_region_classify();
}

/*区域分类，将同一区域名的设备划分到一起*/
void app_leakage_region_classify(void)
{
    u16 i, j;
    u8 add_region_flag;

    /*数量及相关数据清零*/
    p_leakage->region_num = 0;
    p_leakage->sub_device_num = 0;
    memset(p_leakage->region_data, 0, sizeof(p_leakage->region_data));

    /*遍历子系统*/
    for (i = 0; i < APP_LEAKAGE_SUB_DEVICE_NUM; i++)
    {
        add_region_flag = 1; /*添加新区域*/
        /*设备使能*/
        if (ENABLE == p_leakage->sub_device_data[i].flash_data.state)
        {
            p_leakage->sub_device_num++; /*子系统总数量++*/
/********************************************区域划分******************************************************/
            /*遍历区域*/
            for (j = 0; j < APP_LEAKAGE_SUB_DEVICE_NUM; j++)
            {
                if (0 == memcmp(p_leakage->region_data[j].name, p_leakage->sub_device_data[i].flash_data.region_name, APP_LEAKAGE_STRING_NANE_LEN)) /*名称相同*/
                {
                    /*添加子设备*/
                    p_leakage->region_data[j].sub_device_index[p_leakage->region_data[j].sub_device_num] = i; /*绑定子设备索引*/
                    p_leakage->region_data[j].sub_device_num++;                                               /*区域中子系统数据++*/
                    add_region_flag = 0;                                                                      /*不添加新区域*/
                    break;
                }
            }

            /*没有找到相同名称*/
            if (add_region_flag) /*添加新区域*/
            {
                /*复制名称*/
                memcpy(p_leakage->region_data[p_leakage->region_num].name,
                       p_leakage->sub_device_data[i].flash_data.region_name,
                       APP_LEAKAGE_STRING_NANE_LEN);
                // 第一个设备索引为0
                p_leakage->region_data[p_leakage->region_num].sub_device_index[0] = i;
                p_leakage->region_data[p_leakage->region_num].sub_device_num = 1;
                p_leakage->region_num++;
            }
        }
    }
}

/*控制 声 光 继电器 报警*/
static void app_leakage_alarm_contorl(void)
{
    if (0 != p_leakage->alarm_state)
    {
        buzzer.set.on();
        relay.set(BSP_RELAY_CH_ERROR_STATE, USR_ON);
    }
    else
    {
        buzzer.set.off();
        relay.set(BSP_RELAY_CH_ERROR_STATE, USR_OFF);
    }

    /*漏液状态*/
    if (p_leakage->alarm_state & APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE)
    {
        relay.set(BSP_RELAY_CH_LEAKAGE, USR_ON);
    }
    else
    {
        relay.set(BSP_RELAY_CH_LEAKAGE, USR_OFF);
    }
    /*断带状态*/
    if (p_leakage->alarm_state & APP_LEAKAGE_SUB_DEVICE_STATE_OPEN)
    {
        relay.set(BSP_RELAY_CH_OPEN, USR_ON);
    }
    else
    {
        relay.set(BSP_RELAY_CH_OPEN, USR_OFF);
    }
    /*通讯超时*/
    if (p_leakage->alarm_state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT)
    {
        relay.set(BSP_RELAY_CH_COMMINCAION, USR_ON);
    }
    else
    {
        relay.set(BSP_RELAY_CH_COMMINCAION, USR_OFF);
    }
}

/*异常状态设备数量统计*/
void app_leakage_task(void)
{
    static u16 prev_ch_state[APP_LEAKAGE_SUB_DEVICE_NUM][APP_LEAKAGE_SUB_DEVICE_CH_NUM] = {0};
    u16 i, j, k, sub_device_index;

    /* 初始化区域异常统计 */
    for (i = 0; i < p_leakage->region_num; i++)
    {
        p_leakage->region_data[i].leakage_num = 0;
        p_leakage->region_data[i].open_num = 0;
        p_leakage->region_data[i].time_out_num = 0;
    }
    p_leakage->alarm_state = 0;
    /* 检测状态变化并统计异常数量 */
    for (i = 0; i < p_leakage->region_num; i++)
    {
        for (j = 0; j < p_leakage->region_data[i].sub_device_num; j++)
        {
            sub_device_index = p_leakage->region_data[i].sub_device_index[j];

            /* 检查设备是否启用 */
            if (p_leakage->sub_device_data[sub_device_index].flash_data.state != ENABLE)
            {
                continue;
            }

            /* 检查设备是否屏蔽 */
            if (p_leakage->sub_device_data[sub_device_index].shield != UNBLOCKED)
            {
                continue;
            }

            /*历史报警存储*/
            for (k = 0; k < APP_LEAKAGE_SUB_DEVICE_USE_CH_NUM; k++)
            {
                u16 current_state = p_leakage->sub_device_data[sub_device_index].ch_data[k].state;
                u16 prev_state = prev_ch_state[sub_device_index][k];
                u16 leak_distance = p_leakage->sub_device_data[sub_device_index].ch_data[k].distance;

                /* 检测状态变化并记录历史报警 */
                if ((current_state & APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE) &&
                    !(prev_state & APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE))
                {
                    /* 漏液报警开始 - 记录历史报警 */
                    history_add_alarm_record(i, sub_device_index, k, APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE, leak_distance);
                }

                if ((current_state & APP_LEAKAGE_SUB_DEVICE_STATE_OPEN) &&
                    !(prev_state & APP_LEAKAGE_SUB_DEVICE_STATE_OPEN))
                {
                    /* 断带报警开始 - 记录历史报警 */
                    history_add_alarm_record(i, sub_device_index, k, APP_LEAKAGE_SUB_DEVICE_STATE_OPEN, 0);
                }

                if ((current_state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT) &&
                    !(prev_state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT))
                {
                    if (k > 0 && (p_leakage->sub_device_data[sub_device_index].ch_data[0].state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT))
                    {
                        /*第一个通道超时，剩余通道不存储超时报警*/
                    }
                    else
                    {
                        /* 通讯超时报警开始 - 记录历史报警 */
                        history_add_alarm_record(i, sub_device_index, k, APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT, 0);
                    }
                }

                /* 更新历史状态 */
                prev_ch_state[sub_device_index][k] = current_state;
            }

            /* 统计区域异常设备数量 - 按设备统计 */
            for (k = 0; k < APP_LEAKAGE_SUB_DEVICE_USE_CH_NUM; k++)
            {
                u16 current_state = p_leakage->sub_device_data[sub_device_index].ch_data[k].state;

                if (current_state & APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT)
                {
                    p_leakage->region_data[i].time_out_num++;
                    p_leakage->alarm_state |= APP_LEAKAGE_SUB_DEVICE_STATE_TIME_OUT;
                    break;
                }
                else if (current_state & APP_LEAKAGE_SUB_DEVICE_STATE_OPEN)
                {
                    p_leakage->region_data[i].open_num++;
                    p_leakage->alarm_state |= APP_LEAKAGE_SUB_DEVICE_STATE_OPEN;
                }
                else if (current_state & APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE)
                {
                    p_leakage->region_data[i].leakage_num++;
                    p_leakage->alarm_state |= APP_LEAKAGE_SUB_DEVICE_STATE_LEAKAGE;
                }
            }
        }
    }
    /*报警控制 声光报警*/
    app_leakage_alarm_contorl();
}

/* 获取当前时间 */
static void get_current_time(u8 *time_buffer)
{
    /* 年: 2字节 (例如: 2024 -> 0x07 0xE8) */
    uint16_t year = 2000 + DS1302.Time.Year; /* RTC年份通常从2000开始 */
    time_buffer[0] = (year >> 8) & 0xFF;     /* 高字节 */
    time_buffer[1] = year & 0xFF;            /* 低字节 */
    time_buffer[2] = DS1302.Time.Month;      /* 月 */
    time_buffer[3] = DS1302.Time.Day;        /* 日 */
    time_buffer[4] = DS1302.Time.Hour;       /* 时 */
    time_buffer[5] = DS1302.Time.Minute;     /* 分 */
    time_buffer[6] = DS1302.Time.Second;     /* 秒 */
}

/* 从Flash读取历史报警元数据 */
static void history_read_metadata(void)
{
    app_leakage_history_metadata_t temp_metadata;

    w25q32.read(W25Q32_HISTORY_ALARM_METADATA_ADDR,
                (uint8_t *)&temp_metadata,
                sizeof(app_leakage_history_metadata_t));

    if (temp_metadata.total_records <= temp_metadata.max_records &&
        temp_metadata.write_index < temp_metadata.max_records)
    {
        /* 数据有效，复制到全局变量 */
        memcpy(&leakage.history_metadata, &temp_metadata, sizeof(app_leakage_history_metadata_t));
    }
    else
    {
        /* 数据无效，初始化 */
        memset(&leakage.history_metadata, 0, sizeof(app_leakage_history_metadata_t));
        leakage.history_metadata.max_records = MAX_HISTORY_ALARM_RECORDS;

        /* 保存到Flash */
        history_save_metadata();
    }
}

/* 保存历史报警元数据到Flash */
static void history_save_metadata(void)
{
    /* 擦除元数据扇区 */
    w25q32_sector_erase(W25Q32_HISTORY_ALARM_METADATA_ADDR);

    /* 写入元数据 */
    w25q32.write(W25Q32_HISTORY_ALARM_METADATA_ADDR,
                 (uint8_t *)&leakage.history_metadata,
                 sizeof(app_leakage_history_metadata_t));
}

/* 计算记录在Flash中的地址 */
static uint32_t history_calc_record_addr(u32 record_index)
{
    return W25Q32_HISTORY_ALARM_DATA_ADDR +
           (record_index * HISTORY_ALARM_RECORD_SIZE);
}

/* 获取记录所在的扇区地址 */
static uint32_t history_calc_sector_addr(u32 record_index)
{
    uint32_t record_addr = history_calc_record_addr(record_index);
    return record_addr & ~(W25Q32_SECTOR_SIZE - 1); /* 4K对齐 */
}

/* 添加历史报警记录 */
void history_add_alarm_record(u8 region_idx, u8 device_idx, u8 channel, u16 alarm_type, u16 leak_distance)
{
    app_leakage_history_alarm_t new_alarm;
    uint32_t write_addr;

    /* 填充报警记录 */
    memset(&new_alarm, 0, sizeof(app_leakage_history_alarm_t));

    /* 区域名 */
    if (region_idx < leakage.region_num)
    {
        memcpy(new_alarm.region_name, leakage.region_data[region_idx].name,
               APP_LEAKAGE_STRING_NANE_LEN);
    }

    /* 设备ID和名称 */
    if (device_idx < APP_LEAKAGE_SUB_DEVICE_NUM)
    {
        new_alarm.device_id = leakage.sub_device_data[device_idx].flash_data.modbus_id;
        memcpy(new_alarm.device_name, leakage.sub_device_data[device_idx].flash_data.device_name,
               APP_LEAKAGE_STRING_NANE_LEN);
    }

    /* 报警类型、通道和漏液距离 */
    new_alarm.alarm_type = alarm_type;
    new_alarm.channel = channel;
    new_alarm.leak_distance = leak_distance;

    /* 开始时间 */
    get_current_time(new_alarm.start_time);

    /* 计算写入地址 */
    write_addr = history_calc_record_addr(leakage.history_metadata.write_index);

    /* 计算该记录可能跨越的扇区范围（最多2个扇区） */
    uint32_t start_sector = write_addr & ~(W25Q32_SECTOR_SIZE - 1);
    uint32_t end_addr = write_addr + HISTORY_ALARM_RECORD_SIZE - 1;
    uint32_t end_sector = end_addr & ~(W25Q32_SECTOR_SIZE - 1);
    uint32_t num_sectors = (end_sector - start_sector) / W25Q32_SECTOR_SIZE + 1;

    /* 缓冲区：最多两个扇区，每个扇区4KB */
    uint32_t sectors[2] = {start_sector, (num_sectors > 1) ? end_sector : 0};

    /* 1. 读取所有涉及的扇区到RAM */
    for (uint32_t i = 0; i < num_sectors; i++)
    {
        w25q32.read(sectors[i], sector_buf[i], W25Q32_SECTOR_SIZE);
    }

    /* 2. 擦除这些扇区 */
    for (uint32_t i = 0; i < num_sectors; i++)
    {
        w25q32_sector_erase(sectors[i]);
    }

    /* 3. 在RAM中更新新记录的内容 */
    uint32_t offset_in_start = write_addr - start_sector;
    uint32_t first_part_len = (num_sectors == 1) ? HISTORY_ALARM_RECORD_SIZE : (W25Q32_SECTOR_SIZE - offset_in_start);
    memcpy(sector_buf[0] + offset_in_start, &new_alarm, first_part_len);
    if (num_sectors > 1)
    {
        uint32_t second_part_len = HISTORY_ALARM_RECORD_SIZE - first_part_len;
        memcpy(sector_buf[1], (uint8_t *)&new_alarm + first_part_len, second_part_len);
    }

    /* 4. 将修改后的缓冲区写回Flash */
    for (uint32_t i = 0; i < num_sectors; i++)
    {
        w25q32.write(sectors[i], sector_buf[i], W25Q32_SECTOR_SIZE);
    }

    /* 5. 更新元数据（环形队列） */
    leakage.history_metadata.write_index++;
    if (leakage.history_metadata.write_index >= leakage.history_metadata.max_records)
    {
        leakage.history_metadata.write_index = 0;
    }
    if (leakage.history_metadata.total_records < leakage.history_metadata.max_records)
    {
        leakage.history_metadata.total_records++;
    }

    /* 保存元数据到Flash */
    history_save_metadata();
}

/* 读取历史报警记录 */
static u8 history_read_record(u32 record_index, app_leakage_history_alarm_t *record)
{
    if (record_index >= leakage.history_metadata.total_records)
    {
        return 0; /* 记录索引无效 */
    }

    /* 计算实际存储索引（考虑循环队列） */
    uint32_t actual_index;
    if (leakage.history_metadata.total_records == leakage.history_metadata.max_records)
    {
        /* 缓冲区已满，计算相对索引 */
        actual_index = (leakage.history_metadata.write_index + record_index) % 
                       leakage.history_metadata.max_records;
    }
    else
    {
        /* 缓冲区未满，直接读取 */
        actual_index = record_index;
    }

    uint32_t read_addr = history_calc_record_addr(actual_index);
    w25q32.read(read_addr, (uint8_t *)record, HISTORY_ALARM_RECORD_SIZE);

    return 1;
}

/* 清空所有历史报警记录 */
static void history_clear_all(void)
{
    /* 重置元数据 */
    memset(&leakage.history_metadata, 0, sizeof(app_leakage_history_metadata_t));
    leakage.history_metadata.max_records = MAX_HISTORY_ALARM_RECORDS;

    /* 保存元数据 */
    history_save_metadata();

    /* 擦除所有数据扇区（可选） */
    for (uint32_t i = 0; i < HISTORY_ALARM_SECTORS_NEEDED; i++)
    {
        uint32_t sector_addr = W25Q32_HISTORY_ALARM_DATA_ADDR + i * W25Q32_SECTOR_SIZE;
        w25q32_sector_erase(sector_addr);
    }
}

/* 初始化历史报警模块 */
static void history_init(void)
{
    /* 读取元数据 */
    history_read_metadata();
}
