"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread2"));
var _slate = require("slate");
var _transforms = require("../list/transforms");
var _core = require("../../core");
var _constants = require("../../constants");
var _elementTypes = require("../../constants/element-types");
var _helpers = require("../blockquote/helpers");
var _helpers2 = require("../code-block/helpers");
const KEY_TO_TYPE_FOR_SPACE = {
  // Title shortcut
  '#': _elementTypes.HEADER1,
  '##': _elementTypes.HEADER2,
  '###': _elementTypes.HEADER3,
  '####': _elementTypes.HEADER4,
  '#####': _elementTypes.HEADER5,
  '######': _elementTypes.HEADER6,
  // List shortcut
  '*': _elementTypes.UNORDERED_LIST,
  '-': _elementTypes.UNORDERED_LIST,
  // Reference shortcut key
  '>': _elementTypes.BLOCKQUOTE,
  '```': _elementTypes.CODE_BLOCK
};
const KEY_TO_INLINE_TYPE_FOR_SPACE = {
  // Inline shortcut keys
  '**': _constants.TEXT_STYLE_MAP.BOLD,
  '*': _constants.TEXT_STYLE_MAP.ITALIC,
  '***': _constants.TEXT_STYLE_MAP.BOLD_ITALIC,
  '__': _constants.TEXT_STYLE_MAP.BOLD,
  '_': _constants.TEXT_STYLE_MAP.ITALIC,
  '___': _constants.TEXT_STYLE_MAP.BOLD_ITALIC,
  '`': _constants.TEXT_STYLE_MAP.CODE
};
const getBeforeText = editor => {
  const {
    selection
  } = editor;
  if (selection == null) return {
    beforeText: '',
    range: null
  };
  const {
    anchor
  } = selection;
  const range = {
    anchor,
    focus: {
      path: selection.focus.path,
      offset: 0
    }
  };
  const beforeText = _slate.Editor.string(editor, range) || '';
  return {
    beforeText,
    range
  };
};
const withMarkDown = editor => {
  const {
    insertText
  } = editor;
  const newEditor = editor;

  // When entering a space, convert markdown
  newEditor.insertText = text => {
    const {
      selection
    } = editor;
    if (selection == null) return insertText(text);
    if (_slate.Range.isExpanded(selection)) return insertText(text);
    if ((0, _core.getSelectedNodeByType)(editor, _elementTypes.PARAGRAPH) == null) return insertText(text); // It must be in paragraph
    if (text !== ' ') return insertText(text); // The value must be an input space

    // Gets the text before the space
    const {
      beforeText,
      range
    } = getBeforeText(editor);
    if (!beforeText || !range) return insertText(text);

    // Based on the keyword, find the type of element you want to convert
    const type = KEY_TO_TYPE_FOR_SPACE[beforeText.trim()];
    const italicAndBoldType = KEY_TO_INLINE_TYPE_FOR_SPACE[beforeText.slice(-3)];
    const boldType = KEY_TO_INLINE_TYPE_FOR_SPACE[beforeText.slice(-2)];
    const italicType = KEY_TO_INLINE_TYPE_FOR_SPACE[beforeText.slice(-1)];
    const inlineCode = KEY_TO_INLINE_TYPE_FOR_SPACE[beforeText.slice(-1)];
    if (!type && !boldType && !italicType && !italicAndBoldType) return insertText(text);
    if (italicAndBoldType === _constants.TEXT_STYLE_MAP.BOLD_ITALIC) {
      const SYMBOL = beforeText.slice(-3);
      const restStr = beforeText === null || beforeText === void 0 ? void 0 : beforeText.slice(0, beforeText.length - 3);
      const startOffset = restStr === null || restStr === void 0 ? void 0 : restStr.lastIndexOf(SYMBOL);
      const endOffset = (beforeText === null || beforeText === void 0 ? void 0 : beforeText.lastIndexOf(SYMBOL)) + 3;
      if (startOffset === -1) {
        return insertText(text);
      }
      if (startOffset !== -3) {
        _slate.Transforms.delete(editor, {
          at: {
            anchor: {
              path: range.focus.path,
              offset: startOffset
            },
            focus: (0, _objectSpread2.default)({}, selection.focus)
          },
          voids: true
        });
        const newText = beforeText.slice(startOffset + 3, endOffset - 3);
        _slate.Editor.addMark(editor, _constants.TEXT_STYLE_MAP.BOLD, true);
        _slate.Editor.addMark(editor, _constants.TEXT_STYLE_MAP.ITALIC, true);
        insertText(newText);
        _slate.Editor.removeMark(editor, _constants.TEXT_STYLE_MAP.BOLD);
        _slate.Editor.removeMark(editor, _constants.TEXT_STYLE_MAP.ITALIC);
        return;
      }
      return;
    }
    if (boldType === _constants.TEXT_STYLE_MAP.BOLD) {
      const SYMBOL = beforeText.slice(-2);
      const restStr = beforeText.slice(0, beforeText.length - 2);
      const startOffset = restStr.lastIndexOf(SYMBOL);
      const endOffset = beforeText.lastIndexOf(SYMBOL) + 2;
      if (startOffset === -1) {
        return insertText(text);
      }
      _slate.Transforms.delete(editor, {
        at: {
          anchor: {
            path: range.focus.path,
            offset: startOffset
          },
          focus: (0, _objectSpread2.default)({}, selection.focus)
        },
        voids: true
      });
      const newType = boldType.toLowerCase();
      const newText = beforeText.slice(startOffset + 2, endOffset - 2);
      _slate.Editor.addMark(editor, newType, true);
      insertText(newText);
      _slate.Editor.removeMark(editor, newType);
      return;
    }

    // demos
    // 1 '*'
    // 2 'acd * add *'
    if (italicType === _constants.TEXT_STYLE_MAP.ITALIC) {
      const SYMBOL = beforeText.slice(-1);
      const restStr = beforeText === null || beforeText === void 0 ? void 0 : beforeText.slice(0, beforeText.length - 1);
      const startOffset = restStr === null || restStr === void 0 ? void 0 : restStr.lastIndexOf(SYMBOL);
      const endOffset = (beforeText === null || beforeText === void 0 ? void 0 : beforeText.lastIndexOf(SYMBOL)) + 1;

      // start: restStr =  '`' | '   `'
      if (restStr === '' || restStr === '_') {
        return insertText(text);
      }

      // end: restStr = '   _' | 'aaaaa_'
      if (startOffset + 1 === restStr.length) {
        return insertText(text);
      }
      if (startOffset === -1 && restStr.length > 0) {
        return insertText(text);
      }
      if (startOffset !== -1) {
        _slate.Transforms.delete(editor, {
          at: {
            anchor: {
              path: range.focus.path,
              offset: startOffset
            },
            focus: (0, _objectSpread2.default)({}, selection.focus)
          },
          voids: true
        });
        const newType = italicType.toLowerCase();
        const newText = beforeText.slice(startOffset + 1, endOffset - 1);
        _slate.Editor.addMark(editor, newType, true);
        insertText(newText);
        _slate.Editor.removeMark(editor, newType);
        return;
      }
    }
    if (type !== _elementTypes.CODE_BLOCK && inlineCode === _constants.TEXT_STYLE_MAP.CODE) {
      const restStr = beforeText === null || beforeText === void 0 ? void 0 : beforeText.slice(0, beforeText.length - 1);
      const startOffset = restStr === null || restStr === void 0 ? void 0 : restStr.lastIndexOf('`');
      const endOffset = (beforeText === null || beforeText === void 0 ? void 0 : beforeText.lastIndexOf('`')) + 1;

      // start: restStr =  '`' | '   `'
      if (restStr === '' || restStr === '`') {
        return insertText(text);
      }

      // end: restStr = '   `' | 'aaaaa`'
      if (startOffset + 1 === restStr.length) {
        return insertText(text);
      }
      if (startOffset === -1 && restStr.length > 0) {
        return insertText(text);
      }
      if (startOffset !== -1) {
        _slate.Transforms.delete(editor, {
          at: {
            anchor: {
              path: range.focus.path,
              offset: startOffset
            },
            focus: (0, _objectSpread2.default)({}, selection.focus)
          },
          voids: true
        });
        const newType = inlineCode.toLowerCase();
        const newText = beforeText.slice(startOffset + 1, endOffset - 1);
        _slate.Editor.addMark(editor, newType, true);
        insertText(newText);

        // add space with inline code
        _slate.Editor.removeMark(editor, newType);
        insertText(' ');
        return;
      }
    }

    // Delete element
    _slate.Transforms.select(editor, range);
    _slate.Transforms.delete(editor);
    if (type === _elementTypes.UNORDERED_LIST) {
      (0, _transforms.transformsToList)(editor, type);
      return;
    }
    if (type === _elementTypes.BLOCKQUOTE) {
      (0, _helpers.setBlockQuoteType)(editor, false);
      return;
    }
    if (type === _elementTypes.CODE_BLOCK) {
      (0, _helpers2.transformToCodeBlock)(editor);
      return;
    }
    _slate.Transforms.setNodes(editor, {
      type
    });
  };
  return newEditor;
};
var _default = exports.default = withMarkDown;