#pragma once
#ifndef HW_LIB_LIST_H
#define HW_LIB_LIST_H
#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>

typedef struct List_Node_t {    //节点结构
    void *data;
    struct List_Node_t *next;
} List_Node_t;

typedef struct{    //链表结构
    List_Node_t *head;
    List_Node_t *tail;
    long len;
} List_t;

/**
 * @brief   初始化链表
 * @param   list: [输入]     链表指针
 * @return  void
 * @example list_init(&myList_t);
 */
extern void list_init(List_t *list);

/**
 * @brief   检查链表是否为空
 * @param   list: [输入]     链表指针
 * @return  bool            若链表为空返回true，否则返回false
 * @example if (list_is_empty(&myList_t)) { // do something }
 */
extern bool list_is_empty(List_t *list);

/**
 * @brief   在链表尾部插入元素
 * @param   list: [输入]     链表指针
 * @param   data: [输入]     待插入的数据指针
 * @return  void
 * @example list_insert(&myList_t, newData);
 */
extern void list_insert(List_t *list, void *data);

/**
 * @brief   在链表头部插入元素
 * @param   list: [输入]     链表指针
 * @param   data: [输入]     待插入的数据指针
 * @return  void
 * @example list_insert_at_head(&myList_t, newData);
 */
extern void list_insert_at_head(List_t *list, void *data);

/**
 * @brief   在链表尾部插入元素
 * @param   list: [输入]     链表指针
 * @param   data: [输入]     待插入的数据指针
 * @return  void
 * @example list_insert_at_tail(&myList_t, newData);
 */
extern void list_insert_at_tail(List_t *list, void *data);

/**
 * @brief   在指定位置插入元素
 * @param   list: [输入]     链表指针
 * @param   data: [输入]     待插入的数据指针
 * @param   idx: [输入]      插入位置索引
 * @return  void
 * @example list_insert_at_index(&myList_t, newData, 2);
 */
extern void list_insert_at_index(List_t *list, void *data, long idx);

/**
 * @brief   删除链表中指定元素
 * @param   list: [输入]     链表指针
 * @param   key: [输入]      待删除的数据指针
 * @param   compare: [输入]  比较函数指针
 * @return  void*           返回被删除元素的数据，若未找到返回NULL
 * @example deletedData = list_delete(&myList_t, keyData, compareFunc);
 */
extern void *list_delete(List_t *list, void *key, int (*compare)(const void *, const void *));

/**
 * @brief   在链表中查找指定元素
 * @param   list: [输入]     链表指针
 * @param   key: [输入]      待查找的数据指针
 * @param   compare: [输入]  比较函数指针
 * @return  void*           返回找到的元素的数据，若未找到返回NULL
 * @example foundData = list_search(&myList_t, keyData, compareFunc);
 */
extern void *list_search(List_t *list, void *key, int (*compare)(const void *, const void *));

/**
 * @brief   对链表进行排序
 * @param   list: [输入]     链表指针
 * @param   compare: [输入]  比较函数指针
 * @return  void
 * @example list_sort(&myList_t, compareFunc);
 */
extern void list_sort(List_t *list, int (*compare)(const void *, const void *));

/**
 * @brief   遍历链表并对每个元素执行指定操作
 * @param   list: [输入]     链表指针
 * @param   handle: [输入]   处理函数指针
 * @return  void
 * @example list_traverse(&myList_t, handleFunc);
 */
extern void list_traverse(List_t *list, void (*handle)(void *));

/**
 * @brief   反转链表
 * @param   list: [输入]     链表指针
 * @return  void
 * @example list_reverse(&myList_t);
 */
extern void list_reverse(List_t *list);

/**
 * @brief   获取链表长度
 * @param   list: [输入]     链表指针
 * @return  long            返回链表中元素个数
 * @example length = list_get_lenth(&myList_t);
 */
extern long list_get_lenth(List_t *list);

/**
 * @brief   获取链表指定位置的元素
 * @param   list: [输入]     链表指针
 * @param   idx: [输入]      元素索引
 * @return  void*           返回指定位置的元素指针，若索引无效返回NULL
 * @example element = list_get_element(&myList_t, 3);
 */
extern void *list_get_element(List_t *list, int idx);

/**
 * @brief   销毁链表
 * @param   list: [输入]     链表指针
 * @param   destroy: [输入]  数据销毁函数指针
 * @return  void
 * @example list_destroy(&myList_t, destroyFunc);
 */
extern void list_destroy(List_t *list, void (*destroy)(void *data));

#ifdef __cplusplus
}
#endif
#endif //HW_LIB_LIST_H
