"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.upsertLinkText = exports.updateLink = exports.unWrapLinkNode = exports.isMenuDisabled = exports.isLinkType = exports.insertSeafileLink = exports.insertLink = exports.getLinkInfo = exports.getElementHref = exports.generateLinkNode = void 0;
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread2"));
var _slate = require("slate");
var _slugid = _interopRequireDefault(require("slugid"));
var _queries = require("../../core/queries");
var _focusEditor = require("../../core/transforms/focus-editor");
var _constants = require("../../constants");
var _utils = require("../../core/utils");
var _replaceNodeChildren = require("../../core/transforms/replace-node-children");
const isMenuDisabled = function (editor) {
  let readonly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  if (readonly) return true;
  const {
    selection
  } = editor;
  if (!selection) return false;
  const selectedElems = (0, _queries.getSelectedElems)(editor);
  // Check if the selected element is illegal
  const isSelectedIllegalElement = selectedElems.some(elem => {
    const {
      type
    } = elem;
    if (editor.isVoid(elem)) return true;
    if ([_constants.ELementTypes.CODE_BLOCK, _constants.ELementTypes.CODE_LINE].includes(type)) return true;
    return false;
  });
  if (isSelectedIllegalElement) return true;
  return false;
};
exports.isMenuDisabled = isMenuDisabled;
const isLinkType = editor => {
  const [match] = _slate.Editor.nodes(editor, {
    match: n => (0, _queries.getNodeType)(n) === _constants.ELementTypes.LINK,
    universal: true
  });
  return !!match;
};
exports.isLinkType = isLinkType;
const generateLinkNode = (url, title) => {
  const linkNode = {
    type: _constants.ELementTypes.LINK,
    url: url,
    title: title,
    id: _slugid.default.nice(),
    children: [{
      id: _slugid.default.nice(),
      text: title || ''
    }]
  };
  return linkNode;
};

/**
 * @param {Object} props
 * @param {Object} props.editor
 * @param {String} props.url
 * @param {String} props.title
 * @param {InsertPosition} props.insertPosition
 * @param {Object | undefined} props.slateNode
 */
exports.generateLinkNode = generateLinkNode;
const insertLink = props => {
  const {
    editor,
    url,
    title,
    insertPosition = _constants.INSERT_POSITION.CURRENT,
    slateNode
  } = props;
  const {
    selection
  } = editor;
  if (insertPosition === _constants.INSERT_POSITION.CURRENT && isMenuDisabled(editor)) return;
  // We had validated in modal,here we do it again for safety
  if (!title || !url) return;
  if (!selection) return;
  const linkNode = generateLinkNode(url, title);
  if (insertPosition === _constants.INSERT_POSITION.AFTER) {
    let path = _slate.Editor.path(editor, selection);
    if (slateNode && (slateNode === null || slateNode === void 0 ? void 0 : slateNode.type) === _constants.ELementTypes.LIST_ITEM) {
      path = (0, _queries.findPath)(editor, slateNode, []);
      const nextPath = _slate.Path.next(path);
      _slate.Editor.insertNodes(editor, linkNode, {
        at: nextPath
      });
      return;
    }
    const linkNodeWrapper = (0, _utils.generateEmptyElement)(_constants.ELementTypes.PARAGRAPH);
    // LinkNode should be wrapped by p and within text nodes in order to be editable
    linkNodeWrapper.children.push(linkNode, (0, _utils.generateDefaultText)());
    _slate.Transforms.insertNodes(editor, linkNodeWrapper, {
      at: [path[0] + 1]
    });
    (0, _focusEditor.focusEditor)(editor);
    return;
  }
  const isCollapsed = _slate.Range.isCollapsed(selection);
  if (isCollapsed) {
    // If selection is collapsed, we insert a space and then insert link node that help operation easier
    editor.insertText('');
    _slate.Editor.insertFragment(editor, [linkNode]);
    // Using insertText directly causes the added Spaces to be added to the linked text, as in the issue above, so replaced by insertFragment
    _slate.Editor.insertFragment(editor, [{
      id: _slugid.default.nice(),
      text: ''
    }]);
    (0, _focusEditor.focusEditor)(editor);
    return;
  } else {
    const selectedText = _slate.Editor.string(editor, selection); // Selected text
    if (selectedText !== title) {
      // Replace the selected text with the link node if the selected text is different from the entered text
      editor.deleteFragment();
      _slate.Transforms.insertNodes(editor, linkNode);
    } else {
      // Wrap the selected text with the link node if the selected text is the same as the entered text
      _slate.Transforms.wrapNodes(editor, linkNode, {
        split: true,
        at: selection
      });
      _slate.Transforms.collapse(editor, {
        edge: 'end'
      });
    }
  }
  (0, _focusEditor.focusEditor)(editor);
};
exports.insertLink = insertLink;
const insertSeafileLink = _ref => {
  let {
    editor,
    url,
    title,
    selection
  } = _ref;
  (0, _focusEditor.focusEditor)(editor, selection);
  const linkNode = generateLinkNode(url, title);
  const isCollapsed = _slate.Range.isCollapsed(selection);
  if (isCollapsed) {
    // If selection is collapsed, we insert a space and then insert link node that help operation easier
    editor.insertText('');
    _slate.Editor.insertFragment(editor, [linkNode]);
    // Using insertText directly causes the added Spaces to be added to the linked text, as in the issue above, so replaced by insertFragment
    _slate.Editor.insertFragment(editor, [{
      id: _slugid.default.nice(),
      text: ''
    }]);
    (0, _focusEditor.focusEditor)(editor);
    return;
  } else {
    const selectedText = _slate.Editor.string(editor, selection); // Selected text
    if (selectedText !== title) {
      // Replace the selected text with the link node if the selected text is different from the entered text
      editor.deleteFragment();
      _slate.Transforms.insertNodes(editor, linkNode);
    } else {
      // Wrap the selected text with the link node if the selected text is the same as the entered text
      _slate.Transforms.wrapNodes(editor, linkNode, {
        split: true,
        at: selection
      });
      _slate.Transforms.collapse(editor, {
        edge: 'end'
      });
    }
  }
};
exports.insertSeafileLink = insertSeafileLink;
const getElementHref = element => {
  if (!element) return '';
  return element.href || element.url;
};
exports.getElementHref = getElementHref;
const getLinkInfo = editor => {
  const isLinkNode = isLinkType(editor);
  if (!isLinkNode) return null;
  const [match] = _slate.Editor.nodes(editor, {
    match: n => (0, _queries.getNodeType)(n) === _constants.ELementTypes.LINK,
    universal: true
  });
  if (!match) return null;
  const [node, path] = match;
  const showedText = (0, _queries.getEditorString)(editor, path);
  return {
    linkUrl: getElementHref(node),
    linkTitle: showedText || node.title,
    path: path
  };
};
exports.getLinkInfo = getLinkInfo;
const updateLink = (editor, newUrl, newText) => {
  const linkAbove = (0, _queries.getAboveNode)(editor, {
    match: {
      type: _constants.ELementTypes.LINK
    }
  });
  if (!linkAbove) return;
  const {
    href: oldUrl,
    title: oldText
  } = linkAbove[0] || {};
  if (oldUrl !== newUrl || oldText !== newText) {
    _slate.Transforms.setNodes(editor, {
      url: newUrl,
      title: newText
    }, {
      at: linkAbove[1]
    });
  }
  upsertLinkText(editor, {
    text: newText
  });
};
exports.updateLink = updateLink;
const upsertLinkText = (editor, _ref2) => {
  let {
    text
  } = _ref2;
  const newLink = (0, _queries.getAboveNode)(editor, {
    match: {
      type: _constants.ELementTypes.LINK
    }
  });
  if (!newLink) return;
  const [newLInkNode, newLinkPath] = newLink;
  if (text && text.length && text !== (0, _queries.getEditorString)(editor, newLinkPath)) {
    const firstText = newLInkNode.children[0];
    (0, _replaceNodeChildren.replaceNodeChildren)(editor, {
      at: newLinkPath,
      nodes: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, firstText), {}, {
        text
      }),
      insertOptions: {
        select: true
      }
    });
  }
};
exports.upsertLinkText = upsertLinkText;
const unWrapLinkNode = async editor => {
  if (editor.selection == null) return;
  const [linkNode] = _slate.Editor.nodes(editor, {
    match: n => (0, _queries.getNodeType)(n) === _constants.ELementTypes.LINK,
    universal: true
  });
  // Check selection is link node
  if (!linkNode || !linkNode[0]) return;
  _slate.Transforms.unwrapNodes(editor, {
    match: n => (0, _queries.getNodeType)(n) === _constants.ELementTypes.LINK
  });
};
exports.unWrapLinkNode = unWrapLinkNode;