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

/**
 * @brief   双向链表节点结构体
 */
typedef struct Queue_Node_t {
    void *val;                     // 节点值
    struct Queue_Node_t *next;   // 后继节点
    struct Queue_Node_t *prev;   // 前驱节点
} Queue_Node_t;

/**
 * @brief   双端队列结构体
 */
typedef struct {
    Queue_Node_t *front, *rear;  // 头节点 front ，尾节点 rear
    int queSize;                    // 双向队列的长度
    size_t typeSize;                // 元素类型的大小
} Queue_List_t;

/**
 * @brief   创建一个新的双端队列
 * @param   typeSize: [输入]    元素类型的大小
 * @return  Queue_List_t*    返回新创建的双端队列指针
 * @example deque = newQueue_List(sizeof(int));
 */
extern Queue_List_t *newQueue_List(unsigned char size);

/**
 * @brief   销毁双端队列
 * @param   deque: [输入]     双端队列指针
 * @return  void
 * @example delQueue_List(deque);
 */
extern void delQueue_List(Queue_List_t *deque);

/**
 * @brief   获取队列大小
 * @param   deque: [输入]     双端队列指针
 * @return  int                返回队列中元素个数
 * @example size = queue_size(deque);
 */
extern int queue_size(Queue_List_t *deque);

/**
 * @brief   检查队列是否为空
 * @param   deque: [输入]     双端队列指针
 * @return  bool               若队列为空返回true，否则返回false
 * @example if (queue_is_empty(deque)) { // do something }
 */
extern bool queue_is_empty(Queue_List_t *deque);

/**
 * @brief   在队列头部插入元素
 * @param   deque: [输入]     双端队列指针
 * @param   data: [输入]      待插入的数据指针
 * @return  void
 * @example pushFirst(deque, newData);
 */
extern void pushFirst(Queue_List_t *deque, void *data);

/**
 * @brief   在队列尾部插入元素
 * @param   deque: [输入]     双端队列指针
 * @param   data: [输入]      待插入的数据指针
 * @return  void
 * @example pushLast(deque, newData);
 */
extern void pushLast(Queue_List_t *deque, void *data);

/**
 * @brief   获取队列头部元素但不移除
 * @param   deque: [输入]     双端队列指针
 * @return  void*              返回队列头部元素的指针，若队列为空返回NULL
 * @example firstData = peekFirst(deque);
 */
extern void *peekFirst(Queue_List_t *deque);

/**
 * @brief   获取队列尾部元素但不移除
 * @param   deque: [输入]     双端队列指针
 * @return  void*              返回队列尾部元素的指针，若队列为空返回NULL
 * @example lastData = peekLast(deque);
 */
extern void *peekLast(Queue_List_t *deque);
/**
 * @brief   弹出队列头部元素
 * @param   deque: [输入]     双端队列指针
 * @return  void*              返回被弹出的头部元素的指针，若队列为空返回NULL
 * @example poppedData = popFirst(deque);
 */
extern void *popFirst(Queue_List_t *deque);

/**
 * @brief   弹出队列尾部元素
 * @param   deque: [输入]     双端队列指针
 * @return  void*              返回被弹出的尾部元素的指针，若队列为空返回NULL
 * @example poppedData = popLast(deque);
 */
extern void *popLast(Queue_List_t *deque);


#ifdef __cplusplus
}
#endif
#endif //HW_LIB_QUEUE_H
