import { NodeSelection } from 'prosemirror-state';
import { Fragment, Node as PMNode } from 'prosemirror-model';
import { setTextSelection } from './transforms';
import { findParentNodeClosestToPos } from './selection';

export const isNodeSelection = selection => {
    return selection instanceof NodeSelection;
};

export const equalNodeType = (nodeType, node) => {
    return (
        (Array.isArray(nodeType) && nodeType.indexOf(node.type) > -1) ||
    node.type === nodeType
    );
};

export const cloneTr = tr => {
    return Object.assign(Object.create(tr), tr).setTime(Date.now());
};

export const replaceNodeAtPos = (position, content) => tr => {
    const node = tr.doc.nodeAt(position);
    const $pos = tr.doc.resolve(position);
    if (canReplace($pos, content)) {
        tr = tr.replaceWith(position, position + node.nodeSize, content);
        const start = tr.selection.$from.pos - 1;
        // put cursor inside of the inserted node
        tr = setTextSelection(Math.max(start, 0), -1)(tr);
        // move cursor to the start of the node
        tr = setTextSelection(tr.selection.$from.start())(tr);
        return cloneTr(tr);
    }
    return tr;
};

export const canReplace = ($pos, content) => {
    const node = $pos.node($pos.depth);
    return (
        node &&
    node.type.validContent(
        content instanceof Fragment ? content : Fragment.from(content)
    )
    );
};

export const removeNodeAtPos = position => tr => {
    const node = tr.doc.nodeAt(position);
    return cloneTr(tr.delete(position, position + node.nodeSize));
};

export const canInsert = ($pos, content) => {
    const index = $pos.index();

    if (content instanceof Fragment) {
        return $pos.parent.canReplace(index, index, content);
    } else if (content instanceof PMNode) {
        return $pos.parent.canReplaceWith(index, index, content.type);
    }
    return false;
};

export const isEmptyParagraph = node => {
    return !node || (node.type.name === 'paragraph' && node.nodeSize === 2);
};

export const checkInvalidMovements = (
    originIndex,
    targetIndex,
    targets,
    type
) => {
    const direction = originIndex > targetIndex ? -1 : 1;
    const errorMessage = `Target position is invalid, you can't move the ${type} ${originIndex} to ${targetIndex}, the target can't be split. You could use tryToFit option.`;

    if (direction === 1) {
        if (targets.slice(0, targets.length - 1).indexOf(targetIndex) !== -1) {
            throw new Error(errorMessage);
        }
    } else {
        if (targets.slice(1).indexOf(targetIndex) !== -1) {
            throw new Error(errorMessage);
        }
    }

    return true;
};
