/**
 * @file file_list.h
 * @author Chen Jihang (embedded@eseaoptics.com)
 * @brief 文件列表
 * @version 1.0
 * @date 2022-08-25
 * 
 * @copyright ESEA (c) 2020
 * @details
 *      链表头存放两个节点头尾指针
 *      一个存放当前链表，一个是准备接收新的，动态调整切换
 *      每个节点，三个指针，把前后串起来
 *      操作： 
 *      添加： 依据数据大小分配节点空间， 往节点空间添加数据
 *      删除： 取节点， 发送数据，发送完成确认，删除节点
 * 
 */
#ifndef FILE_LIST_H_
#define FILE_LIST_H_
#include <stdint.h>
#include <stddef.h>
#include "ff.h"
/**
 * @brief 链表头
 * 
 */
struct file_list_head
{
    uint64_t file_pointer_used_first;   //< 链表头指针
    uint64_t file_pointer_used_last;    //< 链表尾指针
    uint64_t file_pointer_free_first;   //< 空闲链表头指针
    uint64_t file_pointer_free_last;    //< 空闲链表尾指针
};
/**
 * @brief 链表节点
 * 
 */
struct file_list_node
{
    uint64_t file_pointer_last;     //< 上一个链表节点在文件中的位置
    uint64_t file_pointer_this;     //< 这个链表节点在文件中的位置
    uint64_t file_pointer_next;     //< 下一个链表节点在文件中断位置
    uint64_t size;                  //< 链表节点分配的大小
    uint64_t size_used;             //< 链表节点实际使用的大小
};
/**
 * @brief 文件链表结构体
 * 
 */
struct file_list
{
    FIL fp;                                 //< 文件描述符
    struct file_list_head list_head;        //< 链表头
    struct file_list_node used_node_now;    //< 现在指向的链表节点
    struct file_list_node free_node_now;    //< 现在指向的空闲链表节点
};
int file_list_get_head(struct file_list *p_list,struct file_list_head *p_head);
int file_list_put_head(struct file_list *p_list,struct file_list_head *p_head);
int file_list_get_node(struct file_list *p_list,struct file_list_node *p_node,uint64_t file_pointer);
int file_list_put_node(struct file_list *p_list,struct file_list_node *p_node);
int file_list_get_data(struct file_list *p_list,struct file_list_node *p_node,uint8_t *p_data,uint64_t base_addr,uint64_t size);
int file_list_put_data(struct file_list *p_list,struct file_list_node *p_node,uint8_t *p_data,uint64_t base_addr,uint64_t size);
struct file_list *file_list_create(struct file_list *p_list,char *path);
struct file_list *file_list_open(struct file_list *p_list,char *path);
int file_list_close(struct file_list *p_list);
int file_list_merge_free_node(struct file_list *p_list,struct file_list_node *p_free_node);
struct file_list_node *file_list_alloc(struct file_list *p_list,uint64_t size);
int file_list_del_node(struct file_list *p_list,struct file_list_node *p_used_node);
struct file_list_node *file_list_add_node(struct file_list *p_list,uint64_t size);
struct file_list_node *file_list_get_first_node(struct file_list *p_list);
struct file_list_node *file_list_get_next_node(struct file_list *p_list);
struct file_list_node *file_list_get_last_node(struct file_list *p_list);
uint64_t file_list_get_node_size(struct file_list *p_list,struct file_list_node *p_node);
uint64_t file_list_get_node_data(struct file_list *p_list,struct file_list_node *p_node,void *buf,uint64_t base_addr,uint64_t size);
uint64_t file_list_put_node_data(struct file_list *p_list,struct file_list_node *p_node,void *buf,uint64_t base_addr,uint64_t size);
#endif