@Override
    protected TreeNode<K,V> delete(TreeNode<K,V> deleteNode) {
        TreeNode<K,V> spliceNode = null; // either replacement or deleted !

        //case 1, 2
        if (deleteNode.left == null || deleteNode.right == null){
            spliceNode = deleteNode;
        } else //case 3
            spliceNode = successorWithParent(deleteNode); // at most one node ?

        // now do the splice botch
        TreeNode<K,V> spliceChild = null;
        if (spliceNode.left != null){
            spliceChild = spliceNode.left;
        } else {
            spliceChild = spliceNode.right;
        }
        // point orphaned child to grandparent (new parent)
        if (spliceChild != null)
            spliceChild.parent = spliceNode.parent;

        // point new parent at new child
        if (spliceNode.parent == null) { //root
            root = spliceChild;
        } else if (spliceNode == spliceNode.parent.left) {
            spliceNode.parent.left = spliceChild;
        } else {
            spliceNode.parent.right = spliceChild;
        }

        // case 3
        if (deleteNode != spliceNode) {
            deleteNode.key = spliceNode.key;
            deleteNode.value = spliceNode.value;
        }

        return spliceNode;
    }