#ifndef SWIFT_DATA_BST_H
#define SWIFT_DATA_BST_H

#include <swift/stdlib.h>

#include <swift/data/api.h>

typedef struct swift_bst_iter_t swift_bst_iter_t;
typedef struct swift_bst_node_t swift_bst_node_t;
typedef struct swift_bst_tree_t swift_bst_tree_t;

typedef int (* swift_bst_cmp_fn_t)(swift_bst_tree_t *tree,
	swift_bst_node_t *lhs, swift_bst_node_t *rhs);

enum swift_bst_dir_t {
	SWIFT_BST_DIR_LEFT,
	SWIFT_BST_DIR_RIGHT,
};

struct swift_bst_iter_t {
	swift_bst_node_t *node;
};

struct swift_bst_node_t {
	swift_bst_node_t *parent;
	swift_bst_node_t *child[2];
};

struct swift_bst_tree_t {
	swift_bst_cmp_fn_t cmp;
	swift_bst_node_t *root;
};

#define SWIFT_BST_ITER(...) ((swift_bst_iter_t){__VA_ARGS__})

SWIFT_DATA_API bool swift_bst_init_tree(swift_bst_tree_t *tree,
	swift_bst_cmp_fn_t cmp);
SWIFT_DATA_API void swift_bst_term_tree(swift_bst_tree_t *tree);
SWIFT_DATA_API swift_bst_tree_t *swift_bst_new_tree(swift_bst_cmp_fn_t cmp);
SWIFT_DATA_API void swift_bst_del_tree(swift_bst_tree_t *tree);

SWIFT_DATA_API swift_bst_node_t *swift_bst_outermost(swift_bst_node_t *node,
	int dir);
SWIFT_DATA_API swift_bst_iter_t swift_bst_first(swift_bst_tree_t *tree);
SWIFT_DATA_API swift_bst_iter_t swift_bst_last(swift_bst_tree_t *tree);
SWIFT_DATA_API swift_bst_node_t *swift_bst_successor(swift_bst_node_t *node,
	int dir);
SWIFT_DATA_API bool swift_bst_next(swift_bst_iter_t *iter);
SWIFT_DATA_API bool swift_bst_prev(swift_bst_iter_t *iter);

SWIFT_DATA_API void swift_bst_rotate(swift_bst_tree_t *tree,
	swift_bst_node_t *root, size_t dir);
SWIFT_DATA_API swift_bst_node_t *swift_bst_lookup(swift_bst_tree_t *tree,
	swift_bst_node_t *key, size_t *dir, swift_bst_node_t **parent);
SWIFT_DATA_API swift_bst_node_t *swift_bst_search(swift_bst_tree_t *tree,
	swift_bst_node_t *key);
SWIFT_DATA_API swift_bst_node_t *swift_bst_insert(swift_bst_tree_t *tree,
	swift_bst_node_t *node);
SWIFT_DATA_API swift_bst_node_t *swift_bst_remove(swift_bst_tree_t *tree,
	swift_bst_node_t *key);

SWIFT_DATA_API swift_bst_node_t *swift_bst_shift(swift_bst_tree_t *tree);
SWIFT_DATA_API swift_bst_node_t *swift_bst_pop(swift_bst_tree_t *tree);

#endif /* SWIFT_DATA_BST_H */
