#include "flash_ring.h"

extern int last_page_addr;




BufferState_t buffer_init(void) {
    BufferState_t state = {0};
    
    // Ищем последнюю записанную запись
    for (int i = 0; i < RECORDS_PER_PAGE; i++) {
        uint32_t record_addr = LAST_PAGE_ADDR + (i * RECORD_SIZE);
        FlashRecord_t* record = (FlashRecord_t*)record_addr;
        
        // Проверяем валидность записи (не 0xFFFFFFFF)
        if (record->timestamp != 0xFFFFFFFF) {
            state.write_index = i + 1;
            state.initialized = 1;
        } else {
            break;
        }
    }
		
		    // Если буфер заполнен, начинаем с начала
    if (state.write_index >= RECORDS_PER_PAGE) {
        state.write_index = 0;
    }
    
    return state;
}

HAL_StatusTypeDef buffer_write_record(FlashRecord_t* record, BufferState_t* state) {
    HAL_StatusTypeDef status;
    
    // Если нужно стереть страницу (начало нового цикла)
    if (state->write_index == 0 && state->initialized) {
        status = erase_flash_page();
        if (status != HAL_OK) return status;
    }
    
    // Записываем данные
    uint32_t record_addr =  last_page_addr + (state->write_index * RECORD_SIZE);

    status = write_flash_record(record_addr, record);
    if (status != HAL_OK) return status;
    
    // Обновляем индекс
    state->write_index++;
    if (state->write_index >= RECORDS_PER_PAGE) {
        state->write_index = 0;
    }
    
    state->initialized = 1;
    return HAL_OK;
}

HAL_StatusTypeDef erase_flash_page(void) {
    HAL_FLASH_Unlock();
    
    FLASH_EraseInitTypeDef EraseInit = {
        .TypeErase = FLASH_TYPEERASE_PAGES,
        .PageAddress = LAST_PAGE_ADDR,
        .NbPages = 1
    };
    
    uint32_t page_error;
    HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInit, &page_error);
    
    HAL_FLASH_Lock();
    return status;
}
// Запись одной записи
HAL_StatusTypeDef write_flash_record(uint32_t address, FlashRecord_t* record) {
    HAL_FLASH_Unlock();
    HAL_StatusTypeDef status = HAL_OK;
    
    // Записываем данные по 4 байта (слово)
    uint32_t* data_ptr = (uint32_t*)record;
    uint32_t words_to_write = (RECORD_SIZE + 3) / 4;  // округление вверх
    
    for (uint32_t i = 0; i < words_to_write; i++) {
        status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 
                                 address + (i * 4), 
                                 data_ptr[i]);
        if (status != HAL_OK) break;
    }
    
    HAL_FLASH_Lock();
    return status;
}

// Чтение записи по индексу
FlashRecord_t* buffer_read_record(uint32_t index) {
    if (index >= RECORDS_PER_PAGE) return NULL;
    
    uint32_t record_addr = LAST_PAGE_ADDR + (index * RECORD_SIZE);
    FlashRecord_t* record = (FlashRecord_t*)record_addr;
    
    // Проверяем что запись не пустая
    if (record->timestamp == 0xFFFFFFFF) {
        return NULL;
    }
    
    return record;
}
// Получение всех записей в порядке от старых к новым
void buffer_get_all_records(FlashRecord_t* records[], uint32_t* count) {
    *count = 0;
    BufferState_t state = buffer_init();
    
    if (!state.initialized) return;
    
    // Начинаем с текущего write_index (самые старые данные)
    for (int i = 0; i < RECORDS_PER_PAGE; i++) {
        uint32_t idx = (state.write_index + i) % RECORDS_PER_PAGE;
        FlashRecord_t* record = buffer_read_record(idx);
        
        if (record) {
            records[(*count)++] = record;
        }
    }
}
