#ifndef SWIFT_DATA_RB_H
#define SWIFT_DATA_RB_H

#include <swift/stdlib.h>

#include <swift/data/api.h>
#include <swift/data/bst.h>

typedef struct swift_rb_iter_t swift_rb_iter_t;
typedef struct swift_rb_node_t swift_rb_node_t;
typedef struct swift_rb_tree_t swift_rb_tree_t;

typedef int (* swift_rb_cmp_fn_t)(swift_rb_tree_t *tree, swift_rb_node_t *lhs,
	swift_rb_node_t *rhs);

struct swift_rb_iter_t {
	swift_rb_node_t *node;
};

struct swift_rb_node_t {
	swift_bst_node_t bst_node;
	bool is_red;
};

struct swift_rb_tree_t {
	swift_bst_tree_t bst_tree;
	swift_rb_cmp_fn_t cmp;
};

#define SWIFT_RB_ITER(...) ((swift_rb_iter_t){__VA_ARGS__})
#define SWIFT_RB_NODE(ptr) ((ptr) ? \
	(SWIFT_CONTAINER_OF((ptr), swift_rb_node_t, bst_node)) : \
	NULL)
#define SWIFT_RB_TREE(ptr) \
	(SWIFT_CONTAINER_OF((ptr), swift_rb_tree_t, bst_tree))

SWIFT_DATA_API bool swift_rb_init_tree(swift_rb_tree_t *tree,
	swift_rb_cmp_fn_t cmp);
SWIFT_DATA_API void swift_rb_term_tree(swift_rb_tree_t *tree);
SWIFT_DATA_API swift_rb_tree_t *swift_rb_new_tree(swift_rb_cmp_fn_t cmp);
SWIFT_DATA_API void swift_rb_del_tree(swift_rb_tree_t *tree);

SWIFT_DATA_API swift_rb_node_t *swift_rb_get_root(swift_rb_tree_t *tree);
SWIFT_DATA_API swift_rb_node_t *swift_rb_get_parent(swift_rb_node_t *node);
SWIFT_DATA_API swift_rb_node_t *swift_rb_get_child(swift_rb_node_t *node,
	size_t dir);

SWIFT_DATA_API swift_rb_node_t *swift_rb_outermost(swift_rb_node_t *node,
	int dir);
SWIFT_DATA_API swift_rb_iter_t swift_rb_first(swift_rb_tree_t *tree);
SWIFT_DATA_API swift_rb_iter_t swift_rb_last(swift_rb_tree_t *tree);
SWIFT_DATA_API swift_rb_node_t *swift_rb_successor(swift_rb_node_t *node,
	int dir);
SWIFT_DATA_API bool swift_rb_next(swift_rb_iter_t *iter);
SWIFT_DATA_API bool swift_rb_prev(swift_rb_iter_t *iter);

SWIFT_DATA_API void swift_rb_rotate_node(swift_rb_tree_t *tree,
	swift_rb_node_t *root, size_t dir);
SWIFT_DATA_API swift_rb_node_t *swift_rb_search(swift_rb_tree_t *tree,
	swift_rb_node_t *key);
SWIFT_DATA_API swift_rb_node_t *swift_rb_insert(swift_rb_tree_t *tree,
	swift_rb_node_t *node);
SWIFT_DATA_API swift_rb_node_t *swift_rb_remove(swift_rb_tree_t *tree,
	swift_rb_node_t *key);

SWIFT_DATA_API swift_rb_node_t *swift_rb_shift(swift_rb_tree_t *tree);
SWIFT_DATA_API swift_rb_node_t *swift_rb_pop(swift_rb_tree_t *tree);

#endif /* SWIFT_DATA_RB_H */
