// Copyright (2025) Beijing Volcano Engine Technology Ltd.
// SPDX-License-Identifier: Apache-2.0

#ifndef __VOLC_LIST_H__
#define __VOLC_LIST_H__

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief double list
 */
typedef struct _volc_list_node_t {
    struct _volc_list_node_t    *next;
    struct _volc_list_node_t    *prev;
} volc_list_node_t;

typedef struct _volc_list_t {
    volc_list_node_t            *head;
    volc_list_node_t            *tail;
    uint32_t                    count;
} volc_list_t;

/**
 * @brief initialize a list
 */
#define volc_list_init(list) \
    do { \
        (list)->head = NULL; \
        (list)->tail = NULL; \
        (list)->count = 0; \
    } while(0)

/**
 * @brief add a node to the list head
 */
#define volc_list_add(list, node) \
    do { \
        if ((list)->head == NULL) { \
            (list)->head = (list)->tail = node; \
            (node)->prev = (node)->next = NULL; \
        } else { \
            (node)->next = (list)->head; \
            (list)->head->prev = node; \
            (node)->prev = NULL; \
            (list)->head = node; \
        } \
        (list)->count++; \
    } while(0)

/**
 * @brief add a node to the list tail
 */
#define volc_list_add_tail(list, node) \
    do { \
        if ((list)->tail == NULL) { \
            (list)->head = (list)->tail = node; \
            (node)->prev = (node)->next = NULL; \
        } else { \
            (node)->prev = (list)->tail; \
            (list)->tail->next = node; \
            (node)->next = NULL; \
            (list)->tail = node; \
        } \
        (list)->count++; \
    } while(0)

/**
 * @brief delete a node from the list
 */
#define volc_list_del(list, node) \
    do { \
        if ((list)->head == NULL) { \
            break; \
        } \
        if ((list)->head == node) { \
            (list)->head = node->next; \
            if ((list)->head != NULL) { \
                (list)->head->prev = NULL; \
            } else { \
                (list)->tail = NULL; \
            } \
        } else if ((list)->tail == node) { \
            (list)->tail = node->prev; \
            if ((list)->tail != NULL) { \
                (list)->tail->next = NULL; \
            } else { \
                (list)->head = NULL; \
            } \
        } else { \
            if ((node)->prev != NULL && (node)->next != NULL) { \
                (node)->prev->next = (node)->next; \
                (node)->next->prev = (node)->prev; \
            } \
        } \
        (list)->count--; \
        (node)->next = NULL; \
        (node)->prev = NULL; \
    } while(0)

/**
 * @brief check if a list is empty
 */
#define volc_list_empty(list) ((list)->head == NULL)

/**
 * @brief get the first node of a list
 */
#define volc_list_first(list) ((list)->head)

/**
 * @brief get the last node of a list
 */
#define volc_list_last(list) ((list)->tail)

/**
 * @brief iterate through a list
 */
#define volc_list_for_each(list, node) \
    for ((node) = (list)->head; (node) != NULL; (node) = (node)->next)

/**
 * @brief iterate through a list safe against removal of list entry
 */
#define volc_list_for_each_safe(list, node, n) \
    for ((node) = (list)->head, (n) = (node) ? (node)->next : NULL; \
         (node) != NULL; \
         (node) = (n), (n) = (node) ? (node)->next : NULL)

#ifdef __cplusplus
}
#endif

#endif  // __VOLC_LIST_H__