@Override
	protected Node<T> removeValue(T value) {
		// Find node to remove
		Node<T> nodeToRemoved = this.getNode(value);
		if (nodeToRemoved != null) {
			// Find the replacement node
			Node<T> replacementNode = this.getReplacementNode(nodeToRemoved);

			// Find the parent of the replacement node to re-factor the
			// height/balance of the tree
			AVLNode<T> nodeToRefactor = null;
			if (replacementNode != null)
				nodeToRefactor = (AVLNode<T>) replacementNode.parent;
			if (nodeToRefactor == null)
				nodeToRefactor = (AVLNode<T>) nodeToRemoved.parent;
			if (nodeToRefactor != null && nodeToRefactor.equals(nodeToRemoved))
				nodeToRefactor = (AVLNode<T>) replacementNode;

			// Replace the node
			replaceNodeWithNode(nodeToRemoved, replacementNode);

			// Re-balance the tree all the way up the tree
			if (nodeToRefactor != null) {
				while (nodeToRefactor != null) {
					nodeToRefactor.updateHeight();
					balanceAfterDelete(nodeToRefactor);
					nodeToRefactor = (AVLNode<T>) nodeToRefactor.parent;
				}
			}
		}
		return nodeToRemoved;
	}