// ###############################################
        // Private / Protected stuff
        // ###############################################

        /// <summary>
        /// Actual insert method
        /// </summary>
        /// <param name="pre">Predecessor| Node append new TreeNode on</param>
        /// <param name="dir">Direction| Side on which the new Node should be put</param>
        /// <param name="node"></param>
        /// <returns></returns>
        private bool Insert(BinSearchTreeNode pre, Direction dir, DoubleLinkBinSearchTreeNode node)
        {
            switch (dir)
            {
            case Direction.Unset:
                if (Root != null)
                {
                    return(false);
                }
                Root = node;
                break;

            case Direction.Left:
                if (pre.Left != null)
                {
                    return(false);
                }
                pre.Left = node;
                ((DoubleLinkBinSearchTreeNode)pre.Left).Previous = (DoubleLinkBinSearchTreeNode)pre;
                break;

            case Direction.Right:
                if (pre.Right != null)
                {
                    return(false);
                }
                pre.Right = node;
                ((DoubleLinkBinSearchTreeNode)pre.Right).Previous = (DoubleLinkBinSearchTreeNode)pre;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(dir), dir, null);
            }
            return(true);
        }
        /// <summary>
        /// Actual delete method.
        /// </summary>
        /// <param name="pre"></param>
        /// <param name="a"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        internal override (bool, BinSearchTreeNode) Delete(BinSearchTreeNode pre, BinSearchTreeNode a, Direction dir)
        {
            if (a == null)
            {
                return(false, pre);
            }
            if (a.Type == BinSearchTreeNode.NodeType.Symmetric)
            {
                return(DelSymPred(a));
            }

            var b = a.Left ?? a.Right;

            if (pre == null)
            {
                Root = b;
                if (b != null)
                {
                    ((DoubleLinkBinSearchTreeNode)Root).Previous = null;
                }
                return(true, Root);
            }

            if (dir == Direction.Left)
            {
                pre.Left = b;
                if (b != null)
                {
                    ((DoubleLinkBinSearchTreeNode)pre.Left).Previous = (DoubleLinkBinSearchTreeNode)pre;
                }
            }
            else
            {
                pre.Right = b;
                if (b != null)
                {
                    ((DoubleLinkBinSearchTreeNode)pre.Right).Previous = (DoubleLinkBinSearchTreeNode)pre;
                }
            }
            return(true, pre);
        }
        /// <summary>
        /// Helper method.
        /// Use to "remove" node when node has two children
        /// Basic idea is to copy
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected override (bool, BinSearchTreeNode) DelSymPred(BinSearchTreeNode node)
        {
            // get symmetric predecessor
            var symPred = (DoubleLinkBinSearchTreeNode)(MaxNode(node.Left)).Item2;

            // get node bevor symPred
            var preSymPre = symPred.Previous;

            symPred.Previous = null;

            // Steal value from symPred
            var tmp = symPred.Value;


            // Check if the Node bevor symPred is node
            if (preSymPre.Value == node.Value)
            {
                // remove symPred
                node.Left = node.Left.Left;
                if (node.Left != null)
                {
                    ((DoubleLinkBinSearchTreeNode)node.Left).Previous = (DoubleLinkBinSearchTreeNode)node;
                }
            }
            else
            {
                // remove symPred
                preSymPre.Right = symPred.Left;
                if (preSymPre.Right != null)
                {
                    ((DoubleLinkBinSearchTreeNode)preSymPre.Right).Previous = (DoubleLinkBinSearchTreeNode)preSymPre.Right;
                }
            }

            node.Value = tmp;
            return(true, preSymPre);
        }