///<summary>
 /// RotateLeft
 /// Rebalance the tree by rotating the nodes to the right
 ///</summary>
 public void RotateRight(BinarySearchNode x)
 {
     if (!x.IsSentinel && !x.Left.IsSentinel)
     {
         BinarySearchNode y = x.Left;
         x.Left = y.Right;
         if (!y.Right.IsSentinel)
         {
             y.Right.Parent = x;
         }
         y.Parent = x.Parent;
         if (x.Parent != null)
         {
             if (x == x.Parent.Left)
             {
                 x.Parent.Left = y;
             }
             else
             {
                 x.Parent.Right = y;
             }
         }
         else
         {
             this.Root = y;
         }
         y.Right  = x;
         x.Parent = y;
     }
 }
 private RedBlackColors GetColor(BinarySearchNode node)
 {
     if ((node == null) || (node.IsSentinel))
     {
         return(RedBlackColors.Black);
     }
     return((node as RedBlackNode).Color);
 }
        protected override void OnItemDeleted(BinarySearchNode deleted, BinarySearchNode location)
        {
            if (this.IsBlack(deleted))
            {
                bool isleft = location.IsSentinel ? deleted.Parent.Left.IsSentinel : location.IsLeftChild;

                this.OnItemDeletedInternal(isleft, location, deleted.Parent, isleft ? deleted.Parent.Right : deleted.Parent.Left);
            }
            base.OnItemDeleted(deleted, location);
        }
		private BinarySearchNode(bool isSentinel) {
			if(isSentinel) {
				this.rbnLeft = this.rbnParent = this.rbnRight = null;
				this.objData = null;
				this.ordKey = null;
			} else {
				this.rbnLeft = this.rbnRight = BinarySearchNode.Sentinel;
				this.rbnParent = null;
				this.objData = null;
				this.ordKey = null;
			}
		}
 private void OnItemInsertedInternal(BinarySearchNode token)
 {
     if (token.Parent != null)             //case 1: the new node is the root
     {
         if (this.IsRed(token.Parent))     //case 2: the new nodes parent is black
         //Since root must be black, and parent is red, grandparent must exist
         //and grandparent must be black since no two reds are touching
         {
             if (this.IsRed(token.Parent.Sibling))
             {
                 this.SetColor(token.Parent.Sibling, RedBlackColors.Black);
                 this.SetColor(token.Parent, RedBlackColors.Black);
                 this.SetColor(token.Parent.Parent, RedBlackColors.Red);
                 this.OnItemInsertedInternal(token.Parent.Parent);
             }
             else
             {
                 if (token.IsRightChild && token.Parent.IsLeftChild)
                 {
                     this.RotateLeft(token.Parent);
                     token = token.Left;
                 }
                 else if (token.IsLeftChild && token.Parent.IsRightChild)
                 {
                     this.RotateRight(token.Parent);
                     token = token.Right;
                 }
                 this.SetColor(token.Parent, RedBlackColors.Black);
                 this.SetColor(token.Parent.Parent, RedBlackColors.Red);
                 if (token.IsLeftChild && token.Parent.IsLeftChild)
                 {
                     this.RotateRight(token.Parent.Parent);
                 }
                 else
                 {
                     this.RotateLeft(token.Parent.Parent);
                 }
             }
         }
     }
     else
     {
         this.SetColor(token, RedBlackColors.Black);
     }
 }
        /*private void IsColor(BinarySearchNode node, RedBlackColors color) {
         *      if(color == RedBlackColors.Black)
         *              return this.IsBlack(node);
         *      return this.IsRed(node);
         * }*/

        private void SetColor(BinarySearchNode node, RedBlackColors color)
        {
            (node as RedBlackNode).Color = color;
        }
 private bool IsRed(BinarySearchNode node)
 {
     return(this.GetColor(node) == RedBlackColors.Red);
 }
 protected override void OnItemInserted(BinarySearchNode node)
 {
     this.OnItemInsertedInternal(node);
     base.OnItemInserted(node);
 }
        private void OnItemDeletedInternal(bool isleft, BinarySearchNode token, BinarySearchNode parent, BinarySearchNode sibling)
        {
            if ((parent == null) || this.IsRed(token))
            {
                if (!token.IsSentinel)
                {
                    this.SetColor(token, RedBlackColors.Black);
                }
            }
            else
            {
                //token can be sentinel
                if (this.IsRed(sibling))
                {
                    this.SetColor(sibling, RedBlackColors.Black);
                    this.SetColor(parent, RedBlackColors.Red);
                    if (isleft)
                    {
                        this.RotateLeft(parent);
                    }
                    else
                    {
                        this.RotateRight(parent);
                    }
                    this.OnItemDeletedInternal(isleft, token, parent, isleft ? parent.Right : parent.Left);
                }                 /*else if(token.Sibling.IsSentinel) {
                                   *    this.OnItemDeletedInternal(token.Parent);
                                   * }*/
                else
                {
                    BinarySearchNode near = isleft ? sibling.Left : sibling.Right;
                    BinarySearchNode far  = isleft ? sibling.Right : sibling.Left;
                    if (this.IsBlack(near) && this.IsBlack(far))
                    {
                        //this holds if both near and far are sentinels
                        //after this, there has to be a red nephew

                        //I am having problem with token.sibling being sentinel
                        this.SetColor(sibling, RedBlackColors.Red);
                        this.OnItemDeletedInternal(parent.IsLeftChild, parent, parent.Parent, parent.Sibling);
                    }
                    else if (this.IsRed(near) && this.IsBlack(far))
                    {
                        this.SetColor(near, RedBlackColors.Black);
                        this.SetColor(sibling, RedBlackColors.Red);
                        if (isleft)
                        {
                            this.RotateRight(sibling);
                        }
                        else
                        {
                            this.RotateLeft(sibling);
                        }
                        this.OnItemDeletedInternal(isleft, token, parent, isleft ? parent.Right : parent.Left);
                    }
                    else
                    {
                        this.SetColor(sibling, this.GetColor(parent));
                        this.SetColor(parent, RedBlackColors.Black);
                        this.SetColor(far, RedBlackColors.Black);
                        if (isleft)
                        {
                            this.RotateLeft(parent);
                        }
                        else
                        {
                            this.RotateRight(parent);
                        }
                    }
                }
            }



            /*if(token.IsRoot || this.IsRed(token)) {
             *                              if(!token.IsSentinel)
             *                                      this.SetColor(token, RedBlackColors.Black);
             *                      } else if(token.Sibling.IsSentinel) {
             *                              this.OnItemDeletedInternal(token.Parent);
             *                      } else if(this.IsRed(token.Sibling)) {
             *                              this.SetColor(token.Sibling, RedBlackColors.Black);
             *                              this.SetColor(token.Parent, RedBlackColors.Red);
             *                              if(token.IsLeftChild)
             *                                      this.RotateLeft(token.Parent);
             *                              else
             *                                      this.RotateRight(token.Parent);
             *                              this.OnItemDeletedInternal(token);
             *                      } else if(this.IsBlack(token.Sibling)) {
             *                              BinarySearchNode nearNephew = token.IsRightChild ? token.Sibling.Right : token.Sibling.Left;
             *                              BinarySearchNode farNephew = token.IsRightChild ? token.Sibling.Left : token.Sibling.Right;
             *                              if(this.IsBlack(nearNephew) && this.IsBlack(farNephew)) {
             *                                      //this holds if both near and far are sentinels
             *                                      //after this, there has to be a red nephew
             *                                      this.SetColor(token.Sibling, RedBlackColors.Red);
             *                                      this.OnItemDeletedInternal(token.Parent);
             *                              } else if(nearNephew.IsSentinel || farNephew.IsSentinel) {
             *                                      this.SetColor(farNephew.IsSentinel ? nearNephew : farNephew, RedBlackColors.Black);
             *                                      if(token.IsLeftChild)
             *                                              this.RotateLeft(token.Parent);
             *                                      else
             *                                              this.RotateRight(token.Parent);
             *                              } else {
             *                                      //black sibling, at least one red nephew
             *                                      if(this.IsBlack(farNephew)) {
             *                                              this.SetColor(token.Sibling, RedBlackColors.Red);
             *                                              this.SetColor(nearNephew, RedBlackColors.Black);
             *                                              if(token.IsLeftChild)
             *                                                      this.RotateRight(token.Sibling);
             *                                              else
             *                                                      this.RotateLeft(token.Sibling);
             *                                      }
             *                                      this.SetColor(farNephew, RedBlackColors.Black);
             *                                      if(token.IsLeftChild)
             *                                              this.RotateLeft(token.Parent);
             *                                      else
             *                                              this.RotateRight(token.Parent);
             *                              }
             *                      }
             */



            //since the item deleted and its child were black, in order
            //for the same number of black nodes along any path to leaf,
            //the the token(node that took over for the deleted node)
            //must have a sibling and the sibling must have two children

            /*RedBlackNode parent = token.Parent as RedBlackNode;
             * RedBlackNode sibling = token.Sibling as RedBlackNode;
             *
             * if(sibling.Color == RedBlackColors.Red) {
             *      parent.Color = RedBlackColors.Red;
             *      sibling.Color = RedBlackColors.Black;
             *      if(token.IsLeftChild)
             *              this.RotateLeft(parent);
             *      else
             *              this.RotateRight(parent);
             * }
             *
             * RedBlackNode nephew1 = sibling.Left as RedBlackNode;
             * RedBlackNode nephew2 = sibling.Right as RedBlackNode;
             * if ((parent.Color == RedBlackColors.Black) &&
             *      sibling.Color == RedBlackColors.Black &&
             *      nephew1.Color == RedBlackColors.Black &&
             *      nephew2.Color == RedBlackColors.Black) {
             *      sibling.Color = RedBlackColors.Red;
             *      this.OnItemDeletedInternal(parent);
             * } else {
             *      if ((parent.Color == RedBlackColors.Red) &&
             *              (sibling.Color == RedBlackColors.Black) &&
             *              (nephew1.Color == RedBlackColors.Black) &&
             *              (nephew2.Color == RedBlackColors.Black)) {
             *              sibling.Color = RedBlackColors.Red;
             *              parent.Color = RedBlackColors.Black;
             *      } else {
             *              if (token.IsLeftChild &&
             *                      (sibling.Color == RedBlackColors.Black) &&
             *                      (nephew1.Color == RedBlackColors.Red) &&
             *                      (nephew2.Color == RedBlackColors.Black)) {
             *                      sibling.Color = RedBlackColors.Red;
             *                      nephew1.Color = RedBlackColors.Black;
             *                      this.RotateRight(sibling);
             *              } else if (token.IsRightChild &&
             *                      (sibling.Color == RedBlackColors.Black) &&
             *                      (nephew2.Color == RedBlackColors.Red) &&
             *                      (nephew1.Color == RedBlackColors.Black)) {
             *                      sibling.Color = RedBlackColors.Red;
             *                      nephew2.Color = RedBlackColors.Black;
             *                      this.RotateLeft(sibling);
             *              }
             *              sibling.Color = parent.Color;
             *              parent.Color = RedBlackColors.Black;
             *              if (token.IsLeftChild) {
             *                      nephew2.Color = RedBlackColors.Black;
             *                      this.RotateLeft(parent);
             *              } else {
             *                      nephew1.Color = RedBlackColors.Black;
             *                      this.RotateRight(parent);
             *              }
             *      }
             * }
             * }*/
        }
		static BinarySearchNode() {
			sentinel = new BinarySearchNode(true);
		}