"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.unwrapCodeBlock = exports.transformToCodeBlock = exports.setCodeBlockLanguage = exports.isMenuDisabled = exports.isInCodeBlock = exports.getCodeBlockNodeEntry = void 0;
var _slate = require("slate");
var _elementTypes = require("../../constants/element-types");
var _core = require("../../core");
var _constant = require("./render-elem/constant");
// eslint-disable-next-line no-unused-vars

const isMenuDisabled = (editor, readonly) => {
  if (readonly) return true;
  const {
    selection
  } = editor;
  if (!selection) return true;
  const selectedElements = (0, _core.getSelectedElems)(editor);
  const isSelectedVoid = selectedElements.find(node => editor.isVoid(node));
  if (isSelectedVoid) return true;
  // Disable the menu when selection is not in the paragraph or code block
  const isEnable = selectedElements.every(node => [_elementTypes.CODE_BLOCK, _elementTypes.PARAGRAPH, _elementTypes.CODE_LINE].includes(node.type));
  return !isEnable;
};
exports.isMenuDisabled = isMenuDisabled;
const getCodeBlockNodeEntry = editor => {
  if (!editor.selection) return;
  const [codeBlock] = _slate.Editor.nodes(editor, {
    match: node => node.type === _elementTypes.CODE_BLOCK,
    mode: 'highest'
  });
  return codeBlock;
};
exports.getCodeBlockNodeEntry = getCodeBlockNodeEntry;
const isInCodeBlock = editor => {
  if (!editor.selection) return false;
  const [codeBlock] = _slate.Editor.nodes(editor, {
    match: node => node.type === _elementTypes.CODE_BLOCK,
    mode: 'highest'
  });
  if (!codeBlock) return false;
  const selectedElements = (0, _core.getSelectedElems)(editor);
  const isInCodeBlock = !selectedElements.find(element => ![_elementTypes.CODE_BLOCK, _elementTypes.CODE_LINE].includes(element.type));
  return isInCodeBlock;
};
exports.isInCodeBlock = isInCodeBlock;
const transformToCodeBlock = editor => {
  const selectedElements = (0, _core.getSelectedElems)(editor);
  const selectedCodeBlockNum = selectedElements.reduce((codeBlockNum, node) => node.type === _elementTypes.CODE_BLOCK ? ++codeBlockNum : codeBlockNum, 0);
  if (selectedCodeBlockNum > 0) return;
  const originSelection = editor.selection;
  const {
    anchor: originAnchor,
    focus: originFocus
  } = originSelection;
  const textList = [];
  const nodeEntries = _slate.Editor.nodes(editor, {
    match: node => editor.children.includes(node),
    // Match the highest level node that custom selected
    universal: true
  });
  for (let nodeEntry of nodeEntries) {
    const [node] = nodeEntry;
    if (node) {
      textList.push(_slate.Node.string(node));
    }
  }
  // Generate code block
  const codeBlockChildren = textList.map(text => (0, _core.generateElement)(_elementTypes.CODE_LINE, {
    childrenOrText: text
  }));
  const codeBlock = (0, _core.generateElement)(_elementTypes.CODE_BLOCK, {
    childrenOrText: codeBlockChildren,
    props: {
      lang: _constant.EXPLAIN_TEXT
    }
  });
  _slate.Editor.withoutNormalizing(editor, () => {
    _slate.Transforms.removeNodes(editor, {
      mode: 'highest'
    });
    const selectedPath = _slate.Editor.path(editor, originSelection);
    const beginPath = _slate.Point.isBefore(originAnchor, originFocus) ? originAnchor.path : originFocus.path;
    const insertPath = selectedPath && Object.keys(selectedPath).length ? [selectedPath[0]] : [beginPath[0]];
    _slate.Transforms.insertNodes(editor, codeBlock, {
      at: insertPath
    });
    const focusPoint = _slate.Editor.start(editor, insertPath);
    (0, _core.focusEditor)(editor, focusPoint);
    // const atPoint = {
    //   anchor: { offset: 0, path: [insertPath[0], 0, 0] },
    //   focus: { offset: 0, path: [insertPath[0], 0, 0] }
    // };
    // focusEditor(editor, atPoint);
  });
};
exports.transformToCodeBlock = transformToCodeBlock;
const unwrapCodeBlock = editor => {
  const selectedCodeBlock = (0, _core.getSelectedNodeEntryByType)(editor, _elementTypes.CODE_BLOCK);
  if (!selectedCodeBlock) return;
  const selectedCodeBlockPath = selectedCodeBlock[1];
  const codeLineEntries = _slate.Editor.nodes(editor, {
    at: selectedCodeBlockPath,
    match: node => node.type === _elementTypes.CODE_LINE
  });
  const paragraphNodes = [];
  for (const codeLineEntry of codeLineEntries) {
    const [codeLineNode] = codeLineEntry;
    const paragraph = (0, _core.generateElement)(_elementTypes.PARAGRAPH, {
      childrenOrText: _slate.Node.string(codeLineNode)
    });
    paragraphNodes.push(paragraph);
  }
  _slate.Transforms.removeNodes(editor, {
    at: selectedCodeBlockPath,
    match: node => node.type === _elementTypes.CODE_BLOCK,
    mode: 'highest'
  });
  _slate.Transforms.insertNodes(editor, paragraphNodes, {
    at: selectedCodeBlockPath
  });
  const focusPath = [selectedCodeBlockPath[0] + paragraphNodes.length - 1];
  (0, _core.focusEditor)(editor, _slate.Editor.end(editor, focusPath));
};

/**
 * @param {object} editor
 * @param {keyof LANGUAGE_MAP} [lang = EXPLAIN_TEXT] by default is 'none'
 */
exports.unwrapCodeBlock = unwrapCodeBlock;
const setCodeBlockLanguage = (editor, lang, path) => {
  _slate.Transforms.setNodes(editor, {
    lang
  }, {
    at: path
  });
  (0, _core.focusEditor)(editor, editor.selection || _slate.Editor.start(editor, path));
};
exports.setCodeBlockLanguage = setCodeBlockLanguage;