import { Editor } from 'slate';
import { getMentionsCount, isMentionElement } from './utils';
export const withMaxLength = maxLength => function Plugin(editor) {
  const {
    insertData
  } = editor;

  // usual text insertion prevention is handled in onDOMBeforeInput event on the Editable component
  // this case prevents copy-paste of text that would exceed the maxLength
  // copy-paste could have been also handled in onDOMBeforeInput, but for
  // some reason sometimes Slate stops triggering onDOMBeforeInput for copy-paste ¯\_(ツ)_/¯
  if (maxLength) {
    editor.insertData = data => {
      const existingMentionsCount = getMentionsCount(editor.children);
      // other methods for inserting text does not take into account new lines, so when copy-pasting
      // we should also remove them, otherwise there is a bug when entered text cannot be cut and pasted
      // because on paste text length is considered longer due to \n characters
      const text = data.getData('text/plain')?.replace(/\n/g, '');
      const html = data.getData('text/html');
      const parsedHtml = new DOMParser().parseFromString(html, 'text/html');
      const mentionNodes = parsedHtml.querySelectorAll('.mention');
      const mentionsText = Array.from(mentionNodes).map(node => node.innerText).join('');
      const itemsLengthToBeInserted = mentionNodes.length ? text.length - mentionsText.length : text.length;
      if (Editor.string(editor, []).length + itemsLengthToBeInserted + existingMentionsCount <= maxLength) {
        insertData(data);
      }
    };
  }
  return editor;
};
export const withMentions = editor => {
  const {
    isInline,
    isVoid,
    markableVoid
  } = editor;
  editor.isInline = element => {
    return isMentionElement(element.type) || isInline(element);
  };
  editor.isVoid = element => {
    return isMentionElement(element.type) || isVoid(element);
  };
  editor.markableVoid = element => {
    return isMentionElement(element.type) || markableVoid(element);
  };
  return editor;
};