/// <summary>
        /// Return a new tree with the key-value pair inserted
        /// If the key is already present, it replaces the value
        /// This operation is O(Log N) where N is the number of keys
        /// </summary>
        public AvlNode <T> InsertIntoNew(int index, T val)
        {
            if (IsEmpty)
            {
                return(new AvlNode <T>(val));
            }

            AvlNode <T> newLt = _left;
            AvlNode <T> newGt = _right;

            if (index <= _left._count)
            {
                newLt = _left.InsertIntoNew(index, val);
            }
            else
            {
                newGt = _right.InsertIntoNew(index - _left._count - 1, val);
            }

            var newRoot = NewOrMutate(Value, newLt, newGt);

            return(newRoot.FixRootBalance());
        }