/*******************************************************************************
 * @file    mem_hal.h
 * @brief   Memory Hardware Abstraction Layer Interface
 * @author  Charles KWON <charleskwon@medithings.co.kr>
 * @date    2025-02-03
 *
 * @details Provides unified API for different memory types:
 *          - EEPROM (I2C)
 *          - W25Q32RV Flash (SPI)
 *          - Internal Flash (FDS)
 ******************************************************************************/

#ifndef MEM_HAL_H
#define MEM_HAL_H

#include <stdint.h>
#include <stdbool.h>
#include "sdk_errors.h"
#include "mem_config.h"

/*==============================================================================
 * INITIALIZATION
 *============================================================================*/

/**
 * @brief Initialize memory subsystem
 * @return NRF_SUCCESS on success
 */
ret_code_t mem_init(void);

/**
 * @brief Uninitialize memory subsystem
 */
void mem_uninit(void);

/**
 * @brief Check if memory is ready
 * @return true if ready
 */
bool mem_is_ready(void);

/*==============================================================================
 * BASIC READ/WRITE OPERATIONS
 *============================================================================*/

/**
 * @brief Read single byte
 * @param addr Memory address
 * @param out Output buffer
 * @return NRF_SUCCESS on success
 */
ret_code_t mem_read_byte(uint32_t addr, uint8_t *out);

/**
 * @brief Write single byte
 * @param addr Memory address
 * @param data Byte to write
 * @return NRF_SUCCESS on success
 */
ret_code_t mem_write_byte(uint32_t addr, uint8_t data);

/**
 * @brief Read multiple bytes
 * @param addr Start address
 * @param buf Output buffer
 * @param len Number of bytes
 * @return NRF_SUCCESS on success
 */
ret_code_t mem_read_bytes(uint32_t addr, uint8_t *buf, uint16_t len);

/**
 * @brief Write multiple bytes
 * @param addr Start address
 * @param buf Data buffer
 * @param len Number of bytes
 * @return NRF_SUCCESS on success
 */
ret_code_t mem_write_bytes(uint32_t addr, const uint8_t *buf, uint16_t len);

/*==============================================================================
 * WORD/DWORD OPERATIONS
 *============================================================================*/

/**
 * @brief Read 16-bit word
 */
ret_code_t mem_read_word(uint32_t addr, uint16_t *out);

/**
 * @brief Write 16-bit word
 */
ret_code_t mem_write_word(uint32_t addr, uint16_t data);

/**
 * @brief Read 32-bit value
 */
ret_code_t mem_read_uint32(uint32_t addr, uint32_t *out);

/**
 * @brief Write 32-bit value
 */
ret_code_t mem_write_uint32(uint32_t addr, uint32_t data);

/*==============================================================================
 * ARRAY OPERATIONS
 *============================================================================*/

/**
 * @brief Read array of 16-bit values
 */
ret_code_t mem_read_uint16_array(uint32_t addr, uint16_t *arr, uint16_t count);

/**
 * @brief Write array of 16-bit values
 */
ret_code_t mem_write_uint16_array(uint32_t addr, const uint16_t *arr, uint16_t count);

/*==============================================================================
 * ENCRYPTED OPERATIONS (AES-128 CBC)
 *============================================================================*/

/**
 * @brief Read and decrypt data
 */
ret_code_t mem_read_decrypted(uint32_t addr, uint8_t *buf, uint16_t len);

/**
 * @brief Encrypt and write data
 */
ret_code_t mem_write_encrypted(uint32_t addr, const uint8_t *buf, uint16_t len);

/*==============================================================================
 * FLASH-SPECIFIC OPERATIONS
 *============================================================================*/

/**
 * @brief Erase sector (Flash only, NOP for EEPROM)
 * @param addr Any address within the sector
 * @return NRF_SUCCESS on success
 */
ret_code_t mem_erase_sector(uint32_t addr);

/**
 * @brief Get device ID (Flash only)
 * @param manufacturer_id Output: Manufacturer ID
 * @param device_id Output: Device ID
 * @return NRF_SUCCESS on success
 */
ret_code_t mem_get_device_id(uint8_t *manufacturer_id, uint16_t *device_id);

#endif /* MEM_HAL_H */
