// AVLTreeMap.h
//
// Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// 
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.

#ifndef _AVL_TREE_MAP_H
#define _AVL_TREE_MAP_H

#include <new>

#include <OS.h>

#include "MallocFreeAllocator.h"

// maximal height of a tree
static const int kMaxAVLTreeHeight = 32;

// strategies
namespace AVLTreeMapStrategy {
	// key orders
	template<typename Value> class Ascending;
	template<typename Value> class Descending;

	//! Automatic node strategy (works like STL containers do)
	template <typename Key, typename Value,
			  typename KeyOrder = Ascending<Key>,
			  template <typename> class Allocator = MallocFreeAllocator>
	class Auto;

	//! User managed node strategy (user is responsible for node allocation/deallocation)
//	template <class Node, Node* Node::* NextMember = &Node::next>
//	class User;		

// NodeStrategy::Node must implement this interface.
//	struct Node {
//		Node	*parent;
//		Node	*left;
//		Node	*right;
//		int		balance_factor;
//	};
}

template<typename Parent> class AVLTreeMapIterator;
template<typename Parent> class AVLTreeMapEntry;
template<typename Parent> class AVLTreeMapEntryPointer;

// for convenience
#define _AVL_TREE_MAP_TEMPLATE_LIST template<typename Key, typename Value, \
											 typename NodeStrategy>
#define _AVL_TREE_MAP_CLASS_NAME AVLTreeMap<Key, Value, NodeStrategy>

// AVLTreeMap
template<typename Key, typename Value,
		 typename NodeStrategy = AVLTreeMapStrategy::Auto<Key, Value> >
class AVLTreeMap {
private:
	typedef typename NodeStrategy::Node	Node;
	typedef _AVL_TREE_MAP_CLASS_NAME	Class;
	typedef AVLTreeMapEntry<Class>		Entry;

public:
	class Entry;
	class Iterator;
	class ConstIterator;

public:
	AVLTreeMap();
	~AVLTreeMap();

	inline int Count() const			{ return fNodeCount; }
	inline bool IsEmpty() const			{ return (fNodeCount == 0); }
	void MakeEmpty();

	inline Iterator Begin()				{ return ++Iterator(this, NULL); }
	inline ConstIterator Begin() const	{ return ++ConstIterator(this, NULL); }
	inline Iterator End()				{ return Iterator(this, NULL); }
	inline ConstIterator End() const	{ return ConstIterator(this, NULL); }
	inline Iterator Null()				{ return Iterator(this, NULL); }
	inline ConstIterator Null() const	{ return ConstIterator(this, NULL); }

	Iterator Find(const Key &key);
	Iterator FindClose(const Key &key, bool less);

	status_t Insert(const Key &key, const Value &value, Iterator &iterator);
	status_t Remove(const Key &key);
	Iterator Erase(const Iterator &iterator);

	// debugging
	int Check(Node *node = NULL, int level = 0, bool levelsOnly = false) const;

protected:
	enum {
		NOT_FOUND		= -3,
		DUPLICATE		= -2,
		NO_MEMORY		= -1,
		OK				= 0,
		HEIGHT_CHANGED	= 1,

		LEFT			= -1,
		BALANCED		= 0,
		RIGHT			= 1,
	};

	// rotations
	void _RotateRight(Node **nodeP);
	void _RotateLeft(Node **nodeP);

	// insert
	int _BalanceInsertLeft(Node **node);
	int _BalanceInsertRight(Node **node);
	int _Insert(const Key &key, const Value &value, Node **node,
				Iterator *iterator);

	// remove
	int _BalanceRemoveLeft(Node **node);
	int _BalanceRemoveRight(Node **node);
	int _RemoveRightMostChild(Node **node, Node **foundNode);
	int _Remove(const Key &key, Node **node);
	int _Remove(Node *node);

	void _FreeTree(Node *node);

	// debugging
	void _DumpNode(Node *node) const;

	// strategy shortcuts
	inline Node *Allocate(const Key &key, const Value &value);
	inline void Free(Node *node);
	inline Key &GetKey(Node *node) const;
	inline Value &GetValue(Node *node) const;
	inline int Compare(const Key &a, const Key &b);

protected:
	friend class Entry;
	friend class Iterator;
	friend class ConstIterator;
	friend AVLTreeMapIterator<Class>;
	friend AVLTreeMapIterator<const Class>;

	Node			*fRoot;
	int				fNodeCount;
	NodeStrategy	fStrategy;

	// Iterator
	class Iterator : public AVLTreeMapIterator<_AVL_TREE_MAP_CLASS_NAME> {
	private:
		typedef AVLTreeMapIterator<_AVL_TREE_MAP_CLASS_NAME> SuperClass;

	public:
		inline Iterator();
		inline Iterator(const Iterator &other);

		inline Iterator &operator++();
		inline Iterator operator++(int);
		inline Iterator &operator--();
		inline Iterator operator--(int);
		inline Iterator &operator=(Iterator &other);

	private:
		inline Iterator(_AVL_TREE_MAP_CLASS_NAME *parent, Node *node = NULL);

		friend class _AVL_TREE_MAP_CLASS_NAME;
	};

	// ConstIterator
	class ConstIterator
		: public AVLTreeMapIterator<const _AVL_TREE_MAP_CLASS_NAME> {
	private:
		typedef AVLTreeMapIterator<const _AVL_TREE_MAP_CLASS_NAME> SuperClass;

	public:
		inline ConstIterator();
		inline ConstIterator(const ConstIterator &other);
		inline ConstIterator(const Iterator &other);

		inline ConstIterator &operator++();
		inline ConstIterator operator++(int);
		inline ConstIterator &operator--();
		inline ConstIterator operator--(int);
		inline ConstIterator &operator=(ConstIterator &other);
		inline ConstIterator &operator=(Iterator &other);

	private:
		inline ConstIterator(const _AVL_TREE_MAP_CLASS_NAME *parent,
							 Node *node = NULL);

		friend class _AVL_TREE_MAP_CLASS_NAME;
	};
};


// AVLTreeMapEntry
template<typename Parent>
class AVLTreeMapEntry {
public:
	AVLTreeMapEntry()
		: fParent(NULL), fNode(NULL) {}
	AVLTreeMapEntry(const AVLTreeMapEntry &other)
		: fParent(other.fParent), fNode(other.fNode) {}

	inline const Parent::Key &Key() const
		{ return fParent->GetKey(fNode); }
	inline const Parent::Value &Value() const
		{ return fParent->GetValue(fNode); }

private:
	AVLTreeMapEntry(const Parent *parent, Parent::Node *node)
		: fParent(parent), fNode(node) {}

private:
	friend class AVLTreeMapEntryPointer<Parent>;
	friend class AVLTreeMapIterator<Parent>;
	friend class AVLTreeMapIterator<const Parent>;

	const Parent	*fParent;
	Parent::Node	*fNode;
};

// AVLTreeMapEntryPointer
template<typename Parent>
class AVLTreeMapEntryPointer {
public:
	inline const Entry *operator->() const
	{
		return &fEntry;
	}

private:
	AVLTreeMapEntryPointer(const Parent *parent, Parent::Node *node)
		: fEntry(parent, node) {}

	AVLTreeMapEntryPointer(const AVLTreeMapEntryPointer &);
	AVLTreeMapEntryPointer &operator=(const AVLTreeMapEntryPointer &);

private:
	friend class AVLTreeMapIterator<Parent>;
	friend class AVLTreeMapIterator<const Parent>;

	AVLTreeMapEntry<Parent>	fEntry;
};

// AVLTreeMapIterator
template<typename Parent>
class AVLTreeMapIterator {
private:
	typedef AVLTreeMapIterator<Value, Parent>		Iterator;
	typedef typename Parent::Node					Node;
	typedef typename Parent::Entry					Entry;
	typedef AVLTreeMapEntryPointer<Parent::Class>	EntryPointer;

public:
	inline bool operator==(const Iterator &other) const
	{
		return (fParent == other.fParent && fCurrent == other.fCurrent);
	}

	inline bool operator!=(const Iterator &other) const
	{
		return !(*this == other);
	}

	inline const Entry operator*() const
	{
		return Entry(fParent, fCurrent);
	}

	inline const EntryPointer operator->() const
	{
		return EntryPointer(fParent, fCurrent);
	}

protected:
	inline AVLTreeMapIterator()
		: fParent(NULL),
		  fCurrent(NULL)
	{
	}

	inline AVLTreeMapIterator(const Iterator &other)
		: fParent(other.fParent),
		  fCurrent(other.fCurrent)
	{
	}

	inline AVLTreeMapIterator(Parent *parent, Node *node = NULL)
		: fParent(parent),
		  fCurrent(node)
	{
	}

	inline Iterator &operator++()
	{
		if (fCurrent)
			fCurrent = _GetNextNode(fCurrent);
		else if (fParent)
			fCurrent = _GetLeftMostNode(fParent->fRoot);
		return *this;
	}

	inline Iterator operator++(int)
	{
		Iterator it(*this);
		++*this;
		return it;
	}

	inline Iterator &operator--()
	{
		if (fCurrent)
			fCurrent = _GetPreviousNode(fCurrent);
		else if (fParent)
			fCurrent = _GetRightMostNode(fParent->fRoot);
		return *this;
	}

	inline Iterator operator--(int)
	{
		Iterator it(*this);
		--*this;
		return it;
	}

	inline Iterator &operator=(const Iterator &other)
	{
		fParent = other.fParent;
		fCurrent = other.fCurrent;
		return *this;
	}

	inline operator bool() const
	{
		return fCurrent;
	}

private:
	static inline Node *_GetPreviousNode(Node *node)
	{
		if (node) {
			// The previous node cannot be in the right subtree.
			if (node->left) {
				// We have a left subtree, so go to the right-most node.
				node = node->left;
				while (node->right)
					node = node->right;
			} else {
				// No left subtree: Backtrack our path and stop, where we
				// took the right branch.
				Node *previous;
				do {
					previous = node;
					node = node->parent;
				} while (node && previous == node->left);
			}
		}
		return node;
	}

	static inline Node *_GetNextNode(Node *node)
	{
		if (node) {
			// The next node cannot be in the left subtree.
			if (node->right) {
				// We have a right subtree, so go to the left-most node.
				node = node->right;
				while (node->left)
					node = node->left;
			} else {
				// No right subtree: Backtrack our path and stop, where we
				// took the left branch.
				Node *previous;
				do {
					previous = node;
					node = node->parent;
				} while (node && previous == node->right);
			}
		}
		return node;
	}

	static inline Node *_GetLeftMostNode(Node *node)
	{
		if (node) {
			while (node->left)
				node = node->left;
		}
		return node;
	}

	static inline Node *_GetRightMostNode(Node *node)
	{
		if (node) {
			while (node->right)
				node = node->right;
		}
		return node;
	}

protected:
	Parent	*fParent;
	Node	*fCurrent;
};

// Iterator

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator::Iterator()
	: SuperClass()
{
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator::Iterator(const Iterator &other)
	: SuperClass(other)
{
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator &
_AVL_TREE_MAP_CLASS_NAME::Iterator::operator++()
{
	SuperClass::operator++();
	return *this;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator 
_AVL_TREE_MAP_CLASS_NAME::Iterator::operator++(int)
{
	Iterator it(*this);
	++*this;
	return it;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator &
_AVL_TREE_MAP_CLASS_NAME::Iterator::operator--()
{
	SuperClass::operator--();
	return *this;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator
_AVL_TREE_MAP_CLASS_NAME::Iterator::operator--(int)
{
	Iterator it(*this);
	--*this;
	return it;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator &
_AVL_TREE_MAP_CLASS_NAME::Iterator::operator=(Iterator &other)
{
	*(SuperClass*)this = other;
	return *this;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Iterator::Iterator(_AVL_TREE_MAP_CLASS_NAME *parent,
											 Node *node)
	: SuperClass(parent, node)
{
}

// ConstIterator

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator()
	: SuperClass()
{
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator(
	const ConstIterator &other)
	: SuperClass(other)
{
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator(const Iterator &other)
	: SuperClass(other.fParent, other.fCurrent)
{
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator &
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator++()
{
	SuperClass::operator++();
	return *this;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator++(int)
{
	ConstIterator it(*this);
	++*this;
	return it;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator &
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator--()
{
	SuperClass::operator--();
	return *this;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator--(int)
{
	Iterator it(*this);
	--*this;
	return it;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator &
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator=(ConstIterator &other)
{
	*(SuperClass*)this = other;
	return *this;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator &
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator=(Iterator &other)
{
	fParent = other.fParent;
	fCurrent = other.fCurrent;
	return *this;
}

_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator(
	const _AVL_TREE_MAP_CLASS_NAME *parent, Node *node)
	: SuperClass(parent, node)
{
}


// AVLTreeMap

// constructor
_AVL_TREE_MAP_TEMPLATE_LIST
_AVL_TREE_MAP_CLASS_NAME::AVLTreeMap()
	: fRoot(NULL),
	  fNodeCount(0)
{
}

// destructor
_AVL_TREE_MAP_TEMPLATE_LIST
_AVL_TREE_MAP_CLASS_NAME::~AVLTreeMap()
{
	_FreeTree(fRoot);
	fRoot = NULL;
}

// MakeEmpty
_AVL_TREE_MAP_TEMPLATE_LIST
void
_AVL_TREE_MAP_CLASS_NAME::MakeEmpty()
{
	_FreeTree(fRoot);
	fRoot = NULL;
	fNodeCount = 0;
}

// Find
_AVL_TREE_MAP_TEMPLATE_LIST
_AVL_TREE_MAP_CLASS_NAME::Iterator
_AVL_TREE_MAP_CLASS_NAME::Find(const Key &key)
{
	Node *node = fRoot;
	while (node) {
		int cmp = Compare(key, GetKey(node));
		if (cmp == 0)
			return Iterator(this, node);
		if (cmp < 0)
			node = node->left;
		else
			node = node->right;
	}
	return End();
}

// FindClose
_AVL_TREE_MAP_TEMPLATE_LIST
_AVL_TREE_MAP_CLASS_NAME::Iterator
_AVL_TREE_MAP_CLASS_NAME::FindClose(const Key &key, bool less)
{
	Node *node = fRoot;
	Node *parent = NULL;
	while (node) {
		int cmp = Compare(key, GetKey(node));
		if (cmp == 0)
			break;
		parent = node;
		if (cmp < 0)
			node = node->left;
		else
			node = node->right;
	}
	// not found: try to get close
	if (!node && parent) {
		node = parent;
		int expectedCmp = (less ? -1 : 1);
		int cmp = Compare(GetKey(node), key);
		if (cmp != expectedCmp) {
			// The node's value is less although for a greater value was asked,
			// or the other way around. We need to iterate to the next node in
			// the right directory. If there is no node, we fail.
			if (less)
				return ++Iterator(this, node);
			return --Iterator(this, node);
		}
	}
	return Iterator(this, node);
}

// Insert
_AVL_TREE_MAP_TEMPLATE_LIST
status_t
_AVL_TREE_MAP_CLASS_NAME::Insert(const Key &key, const Value &value,
								 Iterator &iterator)
{
	int result = _Insert(key, value, &fRoot, &iterator);
	switch (result) {
		case OK:
		case HEIGHT_CHANGED:
			return B_OK;
		case NO_MEMORY:
			return B_NO_MEMORY;
		case DUPLICATE:
		default:
			return B_BAD_VALUE;
	}
}

// Remove
_AVL_TREE_MAP_TEMPLATE_LIST
ssize_t
_AVL_TREE_MAP_CLASS_NAME::Remove(const Key &key)
{
	// find node
	Node *node = fRoot;
	while (node) {
		int cmp = Compare(key, GetKey(node));
		if (cmp == 0)
			break;
		else {
			if (cmp < 0)
				node = node->left;
			else
				node = node->right;
		}
	}
	// remove it
	int result = _Remove(node);
	// set result
	switch (result) {
		case OK:
		case HEIGHT_CHANGED:
			return 1;
		case NOT_FOUND:
		default:
			return 0;
	}
}

// Erase
_AVL_TREE_MAP_TEMPLATE_LIST
_AVL_TREE_MAP_CLASS_NAME::Iterator
_AVL_TREE_MAP_CLASS_NAME::Erase(const Iterator &iterator)
{
	Iterator it(iterator);
	if (Node *node = it._GetCurrentNode()) {
		it.GetNext();
		_Remove(node);
		return it;
	}
	return End();
}

// Check
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::Check(Node *node, int level, bool levelsOnly) const
{
	int height = 0;
	if (node) {
		// check root node parent
		if (node == fRoot && node->parent != NULL) {
			printf("Root node has parent: %p\n", node->parent);
			debugger("Root node has parent.");
		}
		// check children's parents
		if (node->left && node->left->parent != node) {
			printf("Left child of node has has wrong parent: %p, should be: "
				   "%p\n", node->left->parent, node);
			_DumpNode(node);
			debugger("Left child node has wrong parent.");
		}
		if (node->right && node->right->parent != node) {
			printf("Right child of node has has wrong parent: %p, should be: "
				   "%p\n", node->right->parent, node);
			_DumpNode(node);
			debugger("Right child node has wrong parent.");
		}
		// check heights
		int leftHeight = Check(node->left, level + 1);
		int rightHeight = Check(node->right, level + 1);
		if (node->balance_factor != rightHeight - leftHeight) {
			printf("Subtree %p at level %d has wrong balance factor: left "
				   "height: %d, right height: %d, balance factor: %d\n",
				   node, level, leftHeight, rightHeight, node->balance_factor);
			_DumpNode(node);
			debugger("Node has wrong balance factor.");
		}
		// check AVL property
		if (!levelsOnly && (leftHeight - rightHeight > 1
							|| leftHeight - rightHeight < -1)) {
			printf("Subtree %p at level %d violates the AVL property: left "
				   "height: %d, right height: %d\n", node, level, leftHeight,
				   rightHeight);
			_DumpNode(node);
			debugger("Node violates AVL property.");
		}
		height = (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;
	}
	return height;
}

// _RotateRight
_AVL_TREE_MAP_TEMPLATE_LIST
void
_AVL_TREE_MAP_CLASS_NAME::_RotateRight(Node **nodeP)
{
	// rotate the nodes
	Node *node = *nodeP;
	Node *left = node->left;
//printf("_RotateRight(): balance: node: %d, left: %d\n",
//node->balance_factor, left->balance_factor);
	*nodeP = left;
	left->parent = node->parent;
	node->left = left->right;
	if (left->right)
		left->right->parent = node;
	left->right = node;
	node->parent = left;
	// adjust the balance factors
	// former pivot
	if (left->balance_factor >= 0)
		node->balance_factor++;
	else
		node->balance_factor += 1 - left->balance_factor;
	// former left
	if (node->balance_factor <= 0)
		left->balance_factor++;
	else
		left->balance_factor += node->balance_factor + 1;
//printf("_RotateRight() end: balance: node: %d, left: %d\n",
//node->balance_factor, left->balance_factor);
}

// _RotateLeft
_AVL_TREE_MAP_TEMPLATE_LIST
void
_AVL_TREE_MAP_CLASS_NAME::_RotateLeft(Node **nodeP)
{
	// rotate the nodes
	Node *node = *nodeP;
	Node *right = node->right;
//printf("_RotateLeft(): balance: node: %d, right: %d\n",
//node->balance_factor, right->balance_factor);
	*nodeP = right;
	right->parent = node->parent;
	node->right = right->left;
	if (right->left)
		right->left->parent = node;
	right->left = node;
	node->parent = right;
	// adjust the balance factors
	// former pivot
	if (right->balance_factor <= 0)
		node->balance_factor--;
	else
		node->balance_factor -= right->balance_factor + 1;
	// former right
	if (node->balance_factor >= 0)
		right->balance_factor--;
	else
		right->balance_factor += node->balance_factor - 1;
//printf("_RotateLeft() end: balance: node: %d, right: %d\n",
//node->balance_factor, right->balance_factor);
}

// _BalanceInsertLeft
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_BalanceInsertLeft(Node **node)
{
//printf("_BalanceInsertLeft()\n");
//_DumpNode(*node);
//Check(*node, 0, true);
	int result = HEIGHT_CHANGED;
	if ((*node)->balance_factor < LEFT) {
		// tree is left heavy
		Node **left = &(*node)->left;
		if ((*left)->balance_factor == LEFT) {
			// left left heavy
			_RotateRight(node);
		} else {
			// left right heavy
			_RotateLeft(left);
			_RotateRight(node);
		}
		result = OK;
	} else if ((*node)->balance_factor == BALANCED)
		result = OK;
//printf("_BalanceInsertLeft() done: %d\n", result);
	return result;
}

// _BalanceInsertRight
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_BalanceInsertRight(Node **node)
{
//printf("_BalanceInsertRight()\n");
//_DumpNode(*node);
//Check(*node, 0, true);
	int result = HEIGHT_CHANGED;
	if ((*node)->balance_factor > RIGHT) {
		// tree is right heavy
		Node **right = &(*node)->right;
		if ((*right)->balance_factor == RIGHT) {
			// right right heavy
			_RotateLeft(node);
		} else {
			// right left heavy
			_RotateRight(right);
			_RotateLeft(node);
		}
		result = OK;
	} else if ((*node)->balance_factor == BALANCED)
		result = OK;
//printf("_BalanceInsertRight() done: %d\n", result);
	return result;
}

// _Insert
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_Insert(const Key &key, const Value &value,
								  Node **node, Iterator *iterator)
{
	struct node_info {
		Node	**node;
		bool	left;
	};
	node_info stack[kMaxAVLTreeHeight];
	node_info *top = stack;
	const node_info *const bottom = stack;
	// find insertion point
	while (*node) {
		int cmp = Compare(key, GetKey(*node));
		if (cmp == 0)	// duplicate node
			return DUPLICATE;
		else {
			top->node = node;
			if (cmp < 0) {
				top->left = true;
				node = &(*node)->left;
			} else {
				top->left = false;
				node = &(*node)->right;
			}
			top++;
		}
	}
	// allocate and insert node
	*node = Allocate(key, value);
	if (*node) {
		(*node)->balance_factor = BALANCED;
		fNodeCount++;
	} else
		return NO_MEMORY;
	if (top != bottom)
		(*node)->parent = *top[-1].node;
	// init the iterator
	if (iterator)
		*iterator = Iterator(this, *node);
	// do the balancing
	int result = HEIGHT_CHANGED;
	while (result == HEIGHT_CHANGED && top != bottom) {
		top--;
		node = top->node;
		if (top->left) {
			// left
			(*node)->balance_factor--;
			result = _BalanceInsertLeft(node);
		} else {
			// right
			(*node)->balance_factor++;
			result = _BalanceInsertRight(node);
		}
	}
//Check(*node);
	return result;
}

// _BalanceRemoveLeft
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_BalanceRemoveLeft(Node **node)
{
//printf("_BalanceRemoveLeft()\n");
//_DumpNode(*node);
//Check(*node, 0, true);
	int result = HEIGHT_CHANGED;
	if ((*node)->balance_factor > RIGHT) {
		// tree is right heavy
		Node **right = &(*node)->right;
		if ((*right)->balance_factor == RIGHT) {
			// right right heavy
			_RotateLeft(node);
		} else if ((*right)->balance_factor == BALANCED) {
			// right none heavy
			_RotateLeft(node);
			result = OK;
		} else {
			// right left heavy
			_RotateRight(right);
			_RotateLeft(node);
		}
	} else if ((*node)->balance_factor == RIGHT)
		result = OK;
//printf("_BalanceRemoveLeft() done: %d\n", result);
	return result;
}

// _BalanceRemoveRight
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_BalanceRemoveRight(Node **node)
{
//printf("_BalanceRemoveRight()\n");
//_DumpNode(*node);
//Check(*node, 0, true);
	int result = HEIGHT_CHANGED;
	if ((*node)->balance_factor < LEFT) {
		// tree is left heavy
		Node **left = &(*node)->left;
		if ((*left)->balance_factor == LEFT) {
			// left left heavy
			_RotateRight(node);
		} else if ((*left)->balance_factor == BALANCED) {
			// left none heavy
			_RotateRight(node);
			result = OK;
		} else {
			// left right heavy
			_RotateLeft(left);
			_RotateRight(node);
		}
	} else if ((*node)->balance_factor == LEFT)
		result = OK;
//printf("_BalanceRemoveRight() done: %d\n", result);
	return result;
}

// _RemoveRightMostChild
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_RemoveRightMostChild(Node **node, Node **foundNode)
{
	Node **stack[kMaxAVLTreeHeight];
	Node ***top = stack;
	const Node *const *const *const bottom = stack;
	// find the child
	while ((*node)->right) {
		*top = node;
		top++;
		node = &(*node)->right;
	}
	// found the rightmost child: remove it
	// the found node might have a left child: replace the node with the
	// child
	*foundNode = *node;
	Node *left = (*node)->left;
	if (left)
		left->parent = (*node)->parent;
	*node = left;
	(*foundNode)->left = NULL;
	(*foundNode)->parent = NULL;
	// balancing
	int result = HEIGHT_CHANGED;
	while (result == HEIGHT_CHANGED && top != bottom) {
		top--;
		node = *top;
		(*node)->balance_factor--;
		result = _BalanceRemoveRight(node);
	}
	return result;
}

// _Remove
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_Remove(const Key &key, Node **node)
{
	struct node_info {
		Node	**node;
		bool	left;
	};
	node_info stack[kMaxAVLTreeHeight];
	node_info *top = stack;
	const node_info *const bottom = stack;
	// find node
	while (*node) {
		int cmp = Compare(key, GetKey(*node));
		if (cmp == 0)
			break;
		else {
			top->node = node;
			if (cmp < 0) {
				top->left = true;
				node = &(*node)->left;
			} else {
				top->left = false;
				node = &(*node)->right;
			}
			top++;
		}
	}
	if (!*node)
		return NOT_FOUND;
	// remove and free node
	int result = HEIGHT_CHANGED;
	Node *oldNode = *node;
	Node *replace = NULL;
	if ((*node)->left && (*node)->right) {
		// node has two children
		result = _RemoveRightMostChild(&(*node)->left, &replace);
		replace->parent = (*node)->parent;
		replace->left = (*node)->left;
		replace->right = (*node)->right;
		if ((*node)->left)	// check necessary, if (*node)->left == replace
			(*node)->left->parent = replace;
		(*node)->right->parent = replace;
		replace->balance_factor = (*node)->balance_factor;
		*node = replace;
		if (result == HEIGHT_CHANGED) {
			replace->balance_factor++;
			result = _BalanceRemoveLeft(node);
		}
	} else if ((*node)->left) {
		// node has only left child
		replace = (*node)->left;
		replace->parent = (*node)->parent;
		replace->balance_factor = (*node)->balance_factor + 1;
		*node = replace;
	} else if ((*node)->right) {
		// node has only right child
		replace = (*node)->right;
		replace->parent = (*node)->parent;
		replace->balance_factor = (*node)->balance_factor - 1;
		*node = replace;
	} else {
		// node has no child
		*node = NULL;
	}
	Free(oldNode);
	fNodeCount--;
	// do the balancing
	while (result == HEIGHT_CHANGED && top != bottom) {
		top--;
		node = top->node;
		if (top->left) {
			// left
			(*node)->balance_factor++;
			result = _BalanceRemoveLeft(node);
		} else {
			// right
			(*node)->balance_factor--;
			result = _BalanceRemoveRight(node);
		}
	}
//Check(*node);
	return result;
}

// _Remove
_AVL_TREE_MAP_TEMPLATE_LIST
int
_AVL_TREE_MAP_CLASS_NAME::_Remove(Node *node)
{
	if (!node)
		return NOT_FOUND;
	// remove and free node
	Node *parent = node->parent;
	bool isLeft = (parent && parent->left == node);
	Node **nodeP
		= (parent ? (isLeft ? &parent->left : &parent->right) : &fRoot);
	int result = HEIGHT_CHANGED;
	Node *replace = NULL;
	if (node->left && node->right) {
		// node has two children
		result = _RemoveRightMostChild(&node->left, &replace);
		replace->parent = parent;
		replace->left = node->left;
		replace->right = node->right;
		if (node->left)	// check necessary, if node->left == replace
			node->left->parent = replace;
		node->right->parent = replace;
		replace->balance_factor = node->balance_factor;
		*nodeP = replace;
		if (result == HEIGHT_CHANGED) {
			replace->balance_factor++;
			result = _BalanceRemoveLeft(nodeP);
		}
	} else if (node->left) {
		// node has only left child
		replace = node->left;
		replace->parent = parent;
		replace->balance_factor = node->balance_factor + 1;
		*nodeP = replace;
	} else if (node->right) {
		// node has only right child
		replace = node->right;
		replace->parent = node->parent;
		replace->balance_factor = node->balance_factor - 1;
		*nodeP = replace;
	} else {
		// node has no child
		*nodeP = NULL;
	}
	Free(node);
	fNodeCount--;
	// do the balancing
	while (result == HEIGHT_CHANGED && parent) {
		node = parent;
		parent = node->parent;
		bool oldIsLeft = isLeft;
		isLeft = (parent && parent->left == node);
		nodeP = (parent ? (isLeft ? &parent->left : &parent->right) : &fRoot);
		if (oldIsLeft) {
			// left
			node->balance_factor++;
			result = _BalanceRemoveLeft(nodeP);
		} else {
			// right
			node->balance_factor--;
			result = _BalanceRemoveRight(nodeP);
		}
	}
//Check(node);
	return result;
}

// _FreeTree
_AVL_TREE_MAP_TEMPLATE_LIST
void
_AVL_TREE_MAP_CLASS_NAME::_FreeTree(Node *node)
{
	if (node) {
		_FreeTree(node->left);
		_FreeTree(node->right);
		fAllocator.Free(node);
	}
}

// _DumpNode
_AVL_TREE_MAP_TEMPLATE_LIST
void
_AVL_TREE_MAP_CLASS_NAME::_DumpNode(Node *node) const
{
	if (!node)
		return;

	enum node_type {
		ROOT,
		LEFT,
		RIGHT,
	};
	struct node_info {
		Node	*node;
		int		id;
		int		parent;
		int		level;
		int		type;
	};

	node_info *queue = new(nothrow) node_info[fNodeCount];
	if (!queue) {
		printf("_Dump(): Insufficient memory for allocating queue.\n");
	}
	node_info *front = queue;
	node_info *back = queue;
	back->node = node;
	back->id = 0;
	back->level = 0;
	back->type = ROOT;
	back++;
	int level = 0;
	int nextID = 1;
	while (front != back) {
		// pop front
		node_info *current = front;
		front++;
		// get to the correct level
		node = current->node;
		if (level < current->level) {
			printf("\n");
			level++;
		}
		// print node
		switch (current->type) {
			case ROOT:
				printf("[%d:%d]", current->id, node->balance_factor);
				break;
			case LEFT:
				printf("[%d:L:%d:%d]", current->id, current->parent,
					   node->balance_factor);
				break;
			case RIGHT:
				printf("[%d:R:%d:%d]", current->id, current->parent,
					   node->balance_factor);
				break;
		}
		// add child nodes
		if (node->left) {
			back->node = node->left;
			back->id = nextID++;
			back->parent = current->id;
			back->level = current->level + 1;
			back->type = LEFT;
			back++;
		}
		if (node->right) {
			back->node = node->right;
			back->id = nextID++;
			back->parent = current->id;
			back->level = current->level + 1;
			back->type = RIGHT;
			back++;
		}
	}
	printf("\n\n");
	delete[] queue;
}

// Allocate
_AVL_TREE_MAP_TEMPLATE_LIST
inline
_AVL_TREE_MAP_CLASS_NAME::Node *
_AVL_TREE_MAP_CLASS_NAME::Allocate(const Key &key, const Value &value)
{
	return fStrategy.Allocate(key, value);
}

// Free
_AVL_TREE_MAP_TEMPLATE_LIST
inline
void
_AVL_TREE_MAP_CLASS_NAME::Free(Node *node)
{
	return fStrategy.Free(node);
}

// GetKey
_AVL_TREE_MAP_TEMPLATE_LIST
inline
Key &
_AVL_TREE_MAP_CLASS_NAME::GetKey(Node *node) const
{
	return fStrategy.GetKey(node);
}

// GetValue
_AVL_TREE_MAP_TEMPLATE_LIST
inline
Value &
_AVL_TREE_MAP_CLASS_NAME::GetValue(Node *node) const
{
	return fStrategy.GetValue(node);
}

// Compare
_AVL_TREE_MAP_TEMPLATE_LIST
inline
int
_AVL_TREE_MAP_CLASS_NAME::Compare(const Key &a, const Key &b)
{
	return fStrategy.Compare(a, b);
}


// strategy parameters

// Ascending
namespace AVLTreeMapStrategy {
template<typename Value>
class Ascending {
	inline int operator()(const Value &a, const Value &b) const
	{
		if (a < b)
			return -1;
		else if (a > b)
			return 1;
		return 0;
	}
};
}

// Descending
namespace AVLTreeMapStrategy {
template<typename Value>
class Descending {
	inline int operator()(const Value &a, const Value &b) const
	{
		if (a < b)
			return -1;
		else if (a > b)
			return 1;
		return 0;
	}
};
}

// strategies

// Auto
namespace AVLTreeMapStrategy {
template <typename Key, typename Value, typename KeyOrder,
		  template <typename> class Allocator>
class Auto {
public:
	class Node
	{
	public:
		Node(const Key &key, const Value &value)
			: key(key),
			  value(value),
			  parent(NULL),
			  left(NULL),
			  right(NULL),
			  balance_factor(0)
		{
		}

		Key		key;
		Value	value;
		Node	*parent;
		Node	*left;
		Node	*right;
		int		balance_factor;
	};

	inline Node *Allocate(const Key &key, const Value &value)
	{
		Node *result = fAllocator.Allocate();
		if (result)
			fAllocator.Construct(result, key, value);
		return result;
	}

	inline void Free(Node *node)
	{
		fAllocator.Destruct(node);
		fAllocator.Deallocate(node);
	}

	inline Key &GetKey(Node *node) const
	{
		return node->key;
	}

	inline Value &GetValue(Node *node) const
	{
		return node->value;
	}

	inline int Compare(const Key &a, const Key &b)
	{
		return fCompare(a, b);
	}

private:
	KeyOrder		fCompare;
	Allocator<Node>	fAllocator;
};
}

#endif	// _AVL_TREE_MAP_H
