/*
 * DWN - Desktop Window Manager
 * Abstract Hash Map Container
 */

#ifndef WM_HASHMAP_H
#define WM_HASHMAP_H

#include "core/wm_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/*==============================================================================
 * Opaque Types
 *============================================================================*/

typedef struct WmHashMap WmHashMap;

/*==============================================================================
 * Function Types
 *============================================================================*/

typedef uint32_t (*WmHashFunc)(const void *key);
typedef bool (*WmKeyEqualFunc)(const void *a, const void *b);
typedef void (*WmHashForeachFunc)(void *key, void *value, void *user_data);

/*==============================================================================
 * Hash Functions
 *============================================================================*/

static inline uint32_t wm_hash_ptr(const void *ptr) {
    uintptr_t p = (uintptr_t)ptr;
    return (uint32_t)(p ^ (p >> 32));
}

static inline uint32_t wm_hash_int(int key) {
    return (uint32_t)key;
}

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

WmHashMap* wm_hashmap_new(void);
WmHashMap* wm_hashmap_new_full(WmHashFunc hash_func, WmKeyEqualFunc key_equal,
                                WmFreeFunc key_free, WmFreeFunc value_free);
WmHashMap* wm_hashmap_new_string_key(void);
void wm_hashmap_destroy(WmHashMap *map);
WmHashMap* wm_hashmap_clone(const WmHashMap *map);

/*==============================================================================
 * Capacity
 *============================================================================*/

size_t wm_hashmap_size(const WmHashMap *map);
bool wm_hashmap_is_empty(const WmHashMap *map);
void wm_hashmap_clear(WmHashMap *map);

/*==============================================================================
 * Element Access
 *============================================================================*/

void* wm_hashmap_get(const WmHashMap *map, const void *key);
void* wm_hashmap_get_or_default(const WmHashMap *map, const void *key, void *default_val);
bool wm_hashmap_contains(const WmHashMap *map, const void *key);

/*==============================================================================
 * Modifiers
 *============================================================================*/

bool wm_hashmap_insert(WmHashMap *map, void *key, void *value);
bool wm_hashmap_insert_no_replace(WmHashMap *map, void *key, void *value);
void* wm_hashmap_set(WmHashMap *map, void *key, void *value);
void* wm_hashmap_remove(WmHashMap *map, const void *key);
bool wm_hashmap_steal(WmHashMap *map, const void *key);

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

typedef struct {
    void *map;          /* Opaque pointer to hashmap */
    size_t bucket;
    void *entry;        /* Opaque pointer to current entry */
    void *next_entry;   /* Opaque pointer to next entry */
} WmHashMapIter;

void wm_hashmap_iter_init(WmHashMapIter *iter, WmHashMap *map);
bool wm_hashmap_iter_next(WmHashMapIter *iter, void **key, void **value);
void wm_hashmap_foreach(const WmHashMap *map, WmHashForeachFunc func, void *user_data);

/*==============================================================================
 * String Helpers
 *============================================================================*/

bool wm_hashmap_insert_string(WmHashMap *map, const char *key, void *value);
void* wm_hashmap_get_string(const WmHashMap *map, const char *key);
bool wm_hashmap_contains_string(const WmHashMap *map, const char *key);
void* wm_hashmap_remove_string(WmHashMap *map, const char *key);

#ifdef __cplusplus
}
#endif

#endif /* WM_HASHMAP_H */
