"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _slate = require("slate");
var _slugid = _interopRequireDefault(require("slugid"));
var _queries = require("../../core/queries");
var _helper = require("./helper");
var _elementTypes = require("../../constants/element-types");
var _constants = require("../../constants");
var _eventTypes = require("../../../constants/event-types");
var _common = require("../../../utils/common");
var _focusEditor = require("../../core/transforms/focus-editor");
var _helper2 = require("../image/helper");
var _isHotkey = _interopRequireDefault(require("is-hotkey"));
var _eventBus = _interopRequireDefault(require("../../../utils/event-bus"));
const withLink = editor => {
  const {
    isInline,
    insertBreak,
    deleteBackward,
    insertText,
    normalizeNode,
    insertData,
    onHotKeyDown
  } = editor;
  const newEditor = editor;

  // Rewrite isInline
  newEditor.isInline = elem => {
    const {
      type
    } = elem;
    if (type === _elementTypes.LINK) {
      return true;
    }
    return isInline(elem);
  };
  newEditor.insertBreak = () => {
    const [selectedElement, path] = _slate.Editor.parent(editor, editor.selection);
    if (selectedElement.type === _elementTypes.LINK) {
      const endPoint = _slate.Range.end(editor.selection);
      const [selectedLeaf] = _slate.Editor.node(editor, endPoint);
      if (selectedLeaf.text.length === endPoint.offset) {
        if (_slate.Range.isExpanded(editor.selection)) {
          _slate.Transforms.delete(editor);
        } else {
          _slate.Transforms.select(editor, {
            path: _slate.Path.next(path),
            offset: 0
          });
        }
      }
    }
    insertBreak();
  };

  // ! bug: insertFragment will insert the same character twice in LinkNode, so we need to delete the first character
  newEditor.insertText = text => {
    const isCollapsed = _slate.Range.isCollapsed(editor.selection);
    const path = _slate.Editor.path(editor, editor.selection);
    const isLinkNode = (0, _queries.getSelectedNodeByType)(editor, _elementTypes.LINK);
    const isFocusAtLinkEnd = _slate.Editor.isEnd(editor, editor.selection.focus, path);
    if (isCollapsed && isLinkNode && isFocusAtLinkEnd) {
      _slate.Editor.insertFragment(newEditor, [{
        id: _slugid.default.nice(),
        text: text
      }]);
      return;
    }
    return insertText(text);
  };
  newEditor.insertData = data => {
    // Paste link content
    const text = data.getData('text/plain');
    if ((0, _common.isUrl)(text) && !(0, _common.isImage)(text)) {
      const link = (0, _helper.generateLinkNode)(text, text);
      _slate.Editor.insertFragment(newEditor, [link], {
        select: true
      });
      return;
    } else if ((0, _common.isUrl)(text) && (0, _common.isImage)(text)) {
      (0, _helper2.insertImage)(newEditor, text);
      return;
    }
    insertData(data);
  };
  newEditor.deleteBackward = unit => {
    const {
      selection
    } = newEditor;
    if (!selection) return deleteBackward(unit);
    // Delete link node
    const isDeletingLinkNode = (0, _helper.isLinkType)(editor);
    if (isDeletingLinkNode) {
      const linkNodeInfo = (0, _helper.getLinkInfo)(editor);
      if (linkNodeInfo && linkNodeInfo.linkTitle.length === 1) {
        const next = _slate.Editor.next(editor);
        const nextPath = _slate.Path.next(linkNodeInfo.path);
        const nextNode = _slate.Editor.node(editor, nextPath);
        (0, _focusEditor.focusEditor)(editor, next[1]);
        _slate.Transforms.select(editor, nextNode[1]);
        _slate.Transforms.delete(newEditor, {
          at: linkNodeInfo.path
        });
        return;
      }
    }
    return deleteBackward(unit);
  };

  // Add 'mod+k' shortcut Key
  newEditor.onHotKeyDown = e => {
    if ((0, _isHotkey.default)('mod+k', e)) {
      e.preventDefault();
      const {
        selection
      } = newEditor;
      const isCollapsed = _slate.Range.isCollapsed(selection);
      const eventBus = _eventBus.default.getInstance();
      if (isCollapsed) {
        eventBus.dispatch(_eventTypes.INTERNAL_EVENTS.INSERT_ELEMENT, {
          type: _constants.ELementTypes.LINK,
          editor
        });
      } else {
        const [firstSelectedNode, ...restNodes] = (0, _queries.getSelectedElems)(newEditor);
        if (!firstSelectedNode) return; // If not select any node, return
        // If firstNode has child nods, recursively check if every child node contains a text node
        const hasTextNode = node => {
          if (_slate.Text.isText(node)) return true;
          if (node.children && node.children.length > 0) {
            return node.children.some(hasTextNode);
          }
        };
        const isSelectTextNodes = hasTextNode(firstSelectedNode);
        if (!isSelectTextNodes) return;
        const linkTitle = window.getSelection().toString();
        eventBus.dispatch(_eventTypes.INTERNAL_EVENTS.INSERT_ELEMENT, {
          type: _constants.ELementTypes.LINK,
          editor: newEditor,
          linkTitle: linkTitle
        });
      }
    }
    return onHotKeyDown && onHotKeyDown(e);
  };

  // Rewrite normalizeNode
  newEditor.normalizeNode = _ref => {
    let [node, path] = _ref;
    const type = (0, _queries.getNodeType)(node);
    if (type !== _elementTypes.LINK) {
      // If the type is not link, perform default normalizeNode
      return normalizeNode([node, path]);
    }

    // If the link is empty, delete it
    const str = _slate.Node.string(node);
    if (str === '') {
      return _slate.Transforms.removeNodes(newEditor, {
        at: path
      });
    }
    return normalizeNode([node, path]);
  };
  return newEditor;
};
var _default = exports.default = withLink;