internal void CheckRoom(QueuedAVLTree <TKey, TValue> tree)
 {
     if (size + 1 > maxSize)
     {
         Dequeue(last.previous, tree, true);
     }
 }
            internal static void Remove(QueueElement element, QueuedAVLTree <TKey, TValue> tree, bool callFromQueue = false)
            {
                element.next.previous = element.previous;
                element.previous.next = element.next;

                if (callFromQueue && element.linkedNode != null)
                {
                    AVLNode.RemoveNode(element.linkedNode, tree, true);
                }
            }
            internal QueueElement Enqueue(AVLNode node, QueuedAVLTree <TKey, TValue> tree)
            {
                if (size > maxSize)
                {
                    Dequeue(last.previous, tree, true);
                }

                QueueElement element = new QueueElement(first, node);

                size++;

                return(element);
            }
            private static void RotateRight(AVLNode node, QueuedAVLTree <TKey, TValue> tree)
            {
                // swap head
                AVLNode oldhead = node.head;

                node.head    = node.head.head;
                oldhead.head = node;

                // change, who is r,l (also isLeft)
                bool tmpb = node.isLeft;

                node.isLeft    = oldhead.isLeft;
                oldhead.isLeft = false;

                if (node.head != null)
                {
                    if (node.isLeft)
                    {
                        node.head.left = node;
                    }
                    else
                    {
                        node.head.right = node;
                    }
                }
                else
                {
                    tree.head = node;
                    node.head = null;
                }

                // update children
                oldhead.left = node.right;
                node.right   = oldhead;

                if (oldhead.left != null)
                {
                    oldhead.left.isLeft = true;
                    oldhead.left.head   = oldhead;
                }

                oldhead.isLeft = false;

                // update balances
                UpdateDepth(oldhead);
                UpdateDepth(node);
            }
            /// <summary>
            /// Called after removing a node - can handle more than 2 or -2 balances on self
            /// </summary>
            internal static void BalanceSelfBubbleUp(AVLNode node, QueuedAVLTree <TKey, TValue> tree)
            {
                while (node != null)
                {
                    node._depthL = node.left == null ? 0 : (GetMaxDepth(node.left) + 1);
                    node._depthR = node.right == null ? 0 : (GetMaxDepth(node.right) + 1);

                    if (Math.Abs(node.balance) > 1)
                    {
                        node.Rebalance(tree);
                    }
                    else
                    {
                        node = node.head;
                    }
                }
            }
            internal static bool FindRemoveItem(AVLNode node, QueuedAVLTree <TKey, TValue> tree, KeyValuePair <TKey, TValue> item, ref int elementCount)
            {
                int compare = item.Key.CompareTo(node.key);

                while (true)
                {
                    if (compare < 0)
                    {
                        node = node.left;

                        if (node != null)
                        {
                            compare = item.Key.CompareTo(node.key);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else if (compare > 0)
                    {
                        node = node.right;

                        if (node != null)
                        {
                            compare = item.Key.CompareTo(node.key);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (node.value.Equals(item.Value))
                        {
                            AVLNode.RemoveNode(node, tree);

                            return(true);
                        }

                        return(false);
                    }
                }
            }
            internal static bool FindRemoveKey(AVLNode node, QueuedAVLTree <TKey, TValue> tree, TKey key, ref int elementCount)
            {
                int compare = key.CompareTo(node.key);

                while (true)
                {
                    if (compare < 0)
                    {
                        node = node.left;

                        if (node != null)
                        {
                            compare = key.CompareTo(node.key);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else if (compare > 0)
                    {
                        node = node.right;

                        if (node != null)
                        {
                            compare = key.CompareTo(node.key);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        AVLNode.RemoveNode(node, tree);

                        return(true);
                    }
                }
            }
            /// <summary>
            /// Called after adding a node
            /// </summary>
            internal static void BalanceBubbleUp(AVLNode node, QueuedAVLTree <TKey, TValue> tree)
            {
                while (node.head != null)
                {
                    if (node._depthL > node._depthR)
                    {
                        if (node.isLeft)
                        {
                            node.head._depthL = node._depthL + 1;
                        }
                        else
                        {
                            node.head._depthR = node._depthL + 1;
                        }
                    }
                    else
                    {
                        if (node.isLeft)
                        {
                            node.head._depthL = node._depthR + 1;
                        }
                        else
                        {
                            node.head._depthR = node._depthR + 1;
                        }
                    }

                    if (Math.Abs(node.head.balance) > 1)
                    {
                        node.head.Rebalance(tree);
                    }
                    else
                    {
                        node = node.head;
                    }
                }
            }
            internal static void AddItem(TKey key, TValue value, QueuedAVLTree <TKey, TValue> tree, ref int elementCount)
            {
                if (!tree.ContainsKey(key))
                {
                    tree.queue.CheckRoom(tree);

                    if (tree.head == null)
                    {
                        tree.head = new AVLNode(key, value, tree);
                        elementCount++;
                        goto LukeIDeletedYourFather;
                    }
                }

                AVLNode headNode = tree.head;
                int     compare  = key.CompareTo(headNode.key);

                while (true)
                {
                    if (compare < 0)
                    {
                        if (headNode.left == null)
                        {
                            headNode.left = new AVLNode(key: key, value: value, tree: tree)
                            {
                                head = headNode, isLeft = true
                            };
                            headNode._depthL = 1;
                            AVLNode.BalanceBubbleUp(headNode, tree);
                            elementCount++;
                            break;
                        }
                        else
                        {
                            headNode = headNode.left;
                            compare  = key.CompareTo(headNode.key);
                        }
                    }
                    else if (compare > 0)
                    {
                        if (headNode.right == null)
                        {
                            headNode.right = new AVLNode(key: key, value: value, tree: tree)
                            {
                                head = headNode, isLeft = false
                            };
                            headNode._depthR = 1;
                            AVLNode.BalanceBubbleUp(headNode, tree);
                            elementCount++;
                            break;
                        }
                        else
                        {
                            headNode = headNode.right;
                            compare  = key.CompareTo(headNode.key);
                        }
                    }
                    else
                    {
                        headNode.value = value;
                        break;
                    }
                }

                LukeIDeletedYourFather :;
            }
            internal static void RemoveNode(AVLNode node, QueuedAVLTree <TKey, TValue> tree, bool callFromQueue = false)
            {
                if (!callFromQueue)
                {
                    tree.queue.Dequeue(node.linkedElement, tree);
                }

                if (node.right == null && node.left == null) // no children
                {
                    if (node.head == null)                   // was the top node
                    {
                        tree.head = null;
                    }
                    else
                    {
                        if (node.isLeft)
                        {
                            node.head.left    = null;
                            node.head._depthL = 0;
                        }
                        else
                        {
                            node.head.right   = null;
                            node.head._depthR = 0;
                        }

                        AVLNode.BalanceSelfBubbleUp(node.head, tree);
                    }
                }
                else if (node.right == null || node.left == null) // one child
                {
                    AVLNode child = node.right != null ? node.right : node.left;

                    if (node.head == null) // was the top node
                    {
                        tree.head  = child;
                        child.head = null;
                    }
                    else
                    {
                        child.isLeft = node.isLeft;

                        if (node.isLeft)
                        {
                            node.head.left     = child;
                            child.head         = node.head;
                            node.head._depthL -= 1;
                        }
                        else
                        {
                            node.head.right    = child;
                            child.head         = node.head;
                            node.head._depthR -= 1;
                        }

                        AVLNode.BalanceSelfBubbleUp(node.head, tree);
                    }
                }
                else // two children :O
                {
                    AVLNode child = node.right, childhead = node.head;

                    while (child.left != null)
                    {
                        childhead = child;
                        child     = child.left;
                    }

                    if (childhead != node.head)
                    {
                        if (child.right != null)
                        {
                            childhead.left     = child.right;
                            child.right.head   = childhead;
                            child.right.isLeft = true;
                            childhead._depthL--;
                        }
                        else
                        {
                            childhead.left    = null;
                            childhead._depthL = 0;
                        }

                        child.right = node.right;
                    }

                    child.left      = node.left;
                    child.left.head = child;
                    child.head      = node.head;
                    child.isLeft    = node.isLeft;

                    if (node.head == null)
                    {
                        tree.head = child;
                    }
                    else
                    {
                        if (node.isLeft)
                        {
                            node.head.left = child;
                        }
                        else
                        {
                            node.head.right = child;
                        }
                    }

                    if (childhead == node.head)
                    {
                        AVLNode.BalanceSelfBubbleUp(child, tree);
                    }
                    else
                    {
                        child.right.head = child;
                        AVLNode.BalanceSelfBubbleUp(childhead, tree);
                    }
                }

                tree.count--;
            }
            private void Rebalance(QueuedAVLTree <TKey, TValue> tree)
            {
                if (Math.Abs(balance) > 2)
                {
                    if (balance < -2)
                    {
                        left.Rebalance(tree);
                    }
                    else
                    {
                        right.Rebalance(tree);
                    }
                }

                if (balance > 1)
                {
                    //          5_2             |              7
                    //      2        7_1        |        5          8
                    //            6       8_1   |     2      6          9
                    //                       9  |

                    //            5             |              5
                    //     2            6       |       3           6
                    //        3                 |    2      4
                    //         4                |

                    //          5               |          5                |           7
                    //    2           8         |     2        7            |      5          8
                    //             7     9      |            6    8         |   2     6          9
                    //            6             |                   9       |

                    if (right.balance > 0)
                    {
                        RotateLeft(right, tree);
                    }
                    else
                    {
                        RotateRight(right.left, tree);

                        RotateLeft(right, tree);
                    }
                }
                else if (balance < -1)
                {
                    //              5           |            5
                    //         4          9     |       4          8
                    //                 8        |                7   9
                    //                7         |

                    //            5             |              5            |           3
                    //     1            6       |       3           6       |      1           5
                    //  0     3                 |    1     4                |   0           4      6
                    //          4               |  0                        |

                    if (left.balance < 0)
                    {
                        RotateRight(left, tree);
                    }
                    else
                    {
                        RotateLeft(left.right, tree);

                        RotateRight(left, tree);
                    }
                }

#if TEST
                checkNodeSelf(this);
#endif
            }
 internal AVLNode(TKey key, TValue value, QueuedAVLTree <TKey, TValue> tree)
 {
     this.key           = key;
     this.value         = value;
     this.linkedElement = tree.queue.Enqueue(this, tree);
 }
 internal void Dequeue(QueueElement element, QueuedAVLTree <TKey, TValue> tree, bool callFromEnqueue = false)
 {
     QueueElement.Remove(element, tree, callFromEnqueue);
     size--;
 }