/*
 * DWN - Desktop Window Manager
 * Generic Container Interface
 */

#ifndef WM_CONTAINER_H
#define WM_CONTAINER_H

#include "wm_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/*==============================================================================
 * Container Lifecycle
 *============================================================================*/

WmContainer* wm_container_create(WmContainerType type, WmDestroyFunc destroy_fn);
void wm_container_destroy(WmContainer *container);
void wm_container_clear(WmContainer *container);

WmContainer* wm_container_clone(const WmContainer *container, WmCloneFunc clone_fn);

/*==============================================================================
 * Container Properties
 *============================================================================*/

WmContainerType wm_container_get_type(const WmContainer *container);
size_t wm_container_size(const WmContainer *container);
bool wm_container_is_empty(const WmContainer *container);

/*==============================================================================
 * List Operations
 *============================================================================*/

/* These work for LIST and QUEUE */
void wm_list_append(WmContainer *list, void *data);
void wm_list_prepend(WmContainer *list, void *data);
void wm_list_insert(WmContainer *list, size_t index, void *data);

bool wm_list_remove(WmContainer *list, void *data);
void* wm_list_remove_at(WmContainer *list, size_t index);

void* wm_list_get(const WmContainer *list, size_t index);
void* wm_list_get_first(const WmContainer *list);
void* wm_list_get_last(const WmContainer *list);

size_t wm_list_index_of(const WmContainer *list, void *data);
bool wm_list_contains(const WmContainer *list, void *data);

void* wm_list_find(const WmContainer *list, WmCompareFunc cmp, const void *key);
void* wm_list_find_custom(const WmContainer *list, 
                          bool (*predicate)(const void *item, const void *user_data),
                          const void *user_data);

void wm_list_sort(WmContainer *list, WmCompareFunc cmp);
void wm_list_reverse(WmContainer *list);

/*==============================================================================
 * Array Operations
 *============================================================================*/

void wm_array_append(WmContainer *array, void *data);
void wm_array_insert(WmContainer *array, size_t index, void *data);
void wm_array_set(WmContainer *array, size_t index, void *data);

void* wm_array_get(const WmContainer *array, size_t index);
void* wm_array_remove_at(WmContainer *array, size_t index);

void wm_array_resize(WmContainer *array, size_t new_size);
void wm_array_reserve(WmContainer *array, size_t capacity);
size_t wm_array_capacity(const WmContainer *array);

void wm_array_compact(WmContainer *array);
void wm_array_sort(WmContainer *array, WmCompareFunc cmp);

/*==============================================================================
 * HashMap Operations
 *============================================================================*/

/* Key types supported */
typedef enum {
    WM_HASH_KEY_STRING,
    WM_HASH_KEY_INT,
    WM_HASH_KEY_POINTER
} WmHashKeyType;

WmContainer* wm_hashmap_create(WmHashKeyType key_type, WmDestroyFunc destroy_fn);

void wm_hashmap_insert(WmContainer *map, const void *key, void *value);
void* wm_hashmap_get(const WmContainer *map, const void *key);
bool wm_hashmap_contains(const WmContainer *map, const void *key);
bool wm_hashmap_remove(WmContainer *map, const void *key);

void* wm_hashmap_lookup(const WmContainer *map, WmCompareFunc cmp, const void *key);

WmContainer* wm_hashmap_get_keys(const WmContainer *map);
WmContainer* wm_hashmap_get_values(const WmContainer *map);

void wm_hashmap_rehash(WmContainer *map, size_t new_capacity);
float wm_hashmap_load_factor(const WmContainer *map);

/* Convenience functions for string keys */
void wm_hashmap_insert_string(WmContainer *map, const char *key, void *value);
void* wm_hashmap_get_string(const WmContainer *map, const char *key);
bool wm_hashmap_contains_string(const WmContainer *map, const char *key);
bool wm_hashmap_remove_string(WmContainer *map, const char *key);

/* Convenience functions for int keys */
void wm_hashmap_insert_int(WmContainer *map, int key, void *value);
void* wm_hashmap_get_int(const WmContainer *map, int key);
bool wm_hashmap_contains_int(const WmContainer *map, int key);
bool wm_hashmap_remove_int(WmContainer *map, int key);

/*==============================================================================
 * Stack Operations
 *============================================================================*/

void wm_stack_push(WmContainer *stack, void *data);
void* wm_stack_pop(WmContainer *stack);
void* wm_stack_peek(const WmContainer *stack);

/*==============================================================================
 * Queue Operations
 *============================================================================*/

void wm_queue_enqueue(WmContainer *queue, void *data);
void* wm_queue_dequeue(WmContainer *queue);
void* wm_queue_peek(const WmContainer *queue);
void* wm_queue_peek_tail(const WmContainer *queue);

/*==============================================================================
 * Tree Operations (if type is TREE)
 *============================================================================*/

typedef struct WmTreeNode WmTreeNode;

WmTreeNode* wm_tree_get_root(const WmContainer *tree);
WmTreeNode* wm_tree_node_get_left(const WmTreeNode *node);
WmTreeNode* wm_tree_node_get_right(const WmTreeNode *node);
WmTreeNode* wm_tree_node_get_parent(const WmTreeNode *node);
void* wm_tree_node_get_data(const WmTreeNode *node);

/*==============================================================================
 * Iteration
 *============================================================================*/

WmIterator* wm_container_iterator(const WmContainer *container);
WmIterator* wm_container_iterator_reverse(const WmContainer *container);

void wm_iterator_destroy(WmIterator *it);
bool wm_iterator_has_next(const WmIterator *it);
void* wm_iterator_next(WmIterator *it);
const void* wm_iterator_peek(const WmIterator *it);

/* HashMap iteration - returns key-value pairs */
typedef struct {
    const void *key;
    void *value;
} WmHashEntry;

WmIterator* wm_hashmap_iterator(const WmContainer *map);
WmHashEntry* wm_hashmap_iterator_next(WmIterator *it);

/*==============================================================================
 * Functional Operations
 *============================================================================*/

typedef void (*WmForeachFunc)(void *item, void *user_data);
typedef void* (*WmMapFunc)(const void *item, void *user_data);
typedef bool (*WmFilterFunc)(const void *item, void *user_data);
typedef void* (*WmReduceFunc)(void *accumulator, const void *item, void *user_data);

void wm_container_foreach(const WmContainer *container, WmForeachFunc func, void *user_data);

WmContainer* wm_container_map(const WmContainer *container, WmContainerType new_type,
                               WmMapFunc func, WmDestroyFunc destroy_fn, void *user_data);

WmContainer* wm_container_filter(const WmContainer *container, 
                                  WmFilterFunc predicate, void *user_data);

void* wm_container_reduce(const WmContainer *container, 
                          WmReduceFunc func, void *initial, void *user_data);

bool wm_container_all_match(const WmContainer *container, 
                            WmFilterFunc predicate, void *user_data);

bool wm_container_any_match(const WmContainer *container,
                            WmFilterFunc predicate, void *user_data);

/*==============================================================================
 * Convenience Constructors
 *============================================================================*/

static inline WmContainer* wm_list_create(WmDestroyFunc destroy_fn) {
    return wm_container_create(WM_CONTAINER_LIST, destroy_fn);
}

static inline WmContainer* wm_array_create(WmDestroyFunc destroy_fn) {
    return wm_container_create(WM_CONTAINER_ARRAY, destroy_fn);
}

static inline WmContainer* wm_hashmap_create_string(WmDestroyFunc destroy_fn) {
    return wm_hashmap_create(WM_HASH_KEY_STRING, destroy_fn);
}

static inline WmContainer* wm_queue_create(WmDestroyFunc destroy_fn) {
    return wm_container_create(WM_CONTAINER_QUEUE, destroy_fn);
}

static inline WmContainer* wm_stack_create(WmDestroyFunc destroy_fn) {
    return wm_container_create(WM_CONTAINER_STACK, destroy_fn);
}

#ifdef __cplusplus
}
#endif

#endif /* WM_CONTAINER_H */
