import { Range, Path, Node, Transforms, Editor, Element, Text } from "slate";
import { ContemberEditor } from "../../../ContemberEditor/index.js";
import { listItemElementPlugin, isListItemElement } from "./ListItemElement.js";
import { orderedListElementPlugin } from "./OrderedListElement.js";
import { unorderedListElementPlugin } from "./UnorderedListElement.js";
import { isListElement } from "./ListElement.js";
import { listHtmlDeserializerFactory } from "./ListHtmlDeserializer.js";
import { dedentListItem } from "./transforms/dedentListItem.js";
import { indentListItem } from "./transforms/indentListItem.js";
const withLists = (editor) => {
  const {
    insertBreak,
    onKeyDown
  } = editor;
  editor.registerElement(listItemElementPlugin);
  editor.registerElement(orderedListElementPlugin);
  editor.registerElement(unorderedListElementPlugin);
  editor.htmlDeserializer.registerPlugin(listHtmlDeserializerFactory());
  Object.assign(editor, {
    insertBreak: () => {
      const { selection } = editor;
      if (!selection || !Range.isCollapsed(selection)) {
        return insertBreak();
      }
      const closestBlockEntry = ContemberEditor.closestBlockEntry(editor);
      if (closestBlockEntry === void 0) {
        return insertBreak();
      }
      const [closestBlock, closestBlockPath] = closestBlockEntry;
      let containingListItem;
      let containingListItemPath;
      if (!isListItemElement(closestBlock)) {
        if (closestBlockPath.length < 2) {
          return insertBreak();
        }
        containingListItemPath = Path.parent(closestBlockPath);
        const closestListItem = Node.get(editor, containingListItemPath);
        if (!isListItemElement(closestListItem)) {
          return insertBreak();
        }
        containingListItem = closestListItem;
      } else {
        containingListItem = closestBlock;
        containingListItemPath = closestBlockPath;
      }
      if (Node.string(containingListItem) !== "") {
        return Transforms.splitNodes(editor, {
          always: true,
          at: selection.focus,
          match: (node) => isListItemElement(node)
        });
      }
      const containingListPath = Path.parent(containingListItemPath);
      const containingList = Node.get(editor, containingListPath);
      if (!isListElement(containingList)) {
        return insertBreak();
      }
      const followingListItemPath = Path.next(containingListItemPath);
      const hasFollowingListItem = Node.has(editor, followingListItemPath);
      if (hasFollowingListItem) {
        const followingListItemNode = Node.get(editor, followingListItemPath);
        if (!isListItemElement(followingListItemNode)) {
          return insertBreak();
        }
        if (containingListItemPath[containingListItemPath.length - 1] === 0) {
          Editor.withoutNormalizing(editor, () => {
            Transforms.removeNodes(editor, { at: containingListItemPath });
            Transforms.insertNodes(editor, editor.createDefaultElement([{ text: "" }]), { at: containingListPath, select: true });
          });
        } else {
          Editor.withoutNormalizing(editor, () => {
            Transforms.removeNodes(editor, { at: containingListItemPath });
            Transforms.splitNodes(editor, { at: containingListItemPath });
            const afterListParent = Path.next(containingListPath);
            Transforms.insertNodes(editor, editor.createDefaultElement([{ text: "" }]), { at: afterListParent, select: true });
          });
        }
      } else {
        Editor.withoutNormalizing(editor, () => {
          const afterListParent = Path.next(containingListPath);
          Transforms.removeNodes(editor, { at: containingListItemPath });
          Transforms.insertNodes(editor, editor.createDefaultElement([{ text: "" }]), { at: afterListParent, select: true });
        });
      }
    },
    onKeyDown: (event) => {
      if (event.key !== "Tab" && event.key !== "Enter" || !editor.selection || !Range.isCollapsed(editor.selection)) {
        return onKeyDown(event);
      }
      const selection = editor.selection;
      const closestBlockEntry = ContemberEditor.closestBlockEntry(editor, { at: selection.focus });
      if (closestBlockEntry === void 0) {
        return onKeyDown(event);
      }
      let [closestBlockElement, closestBlockPath] = closestBlockEntry;
      if (!Element.isElement(closestBlockElement)) {
        return onKeyDown(event);
      }
      if (event.key === "Tab") {
        if (editor.isDefaultElement(closestBlockElement)) {
          [closestBlockElement, closestBlockPath] = Editor.parent(editor, closestBlockPath);
        }
        if (!isListItemElement(closestBlockElement)) {
          return onKeyDown(event);
        }
        const succeeded = event.shiftKey ? dedentListItem(editor, closestBlockElement, closestBlockPath) : indentListItem(editor, closestBlockElement, closestBlockPath);
        if (succeeded) {
          return event.preventDefault();
        }
      } else if (event.key === "Enter" && event.shiftKey) {
        if (editor.isDefaultElement(closestBlockElement)) {
          const [listItem] = Editor.parent(editor, closestBlockPath);
          if (!isListItemElement(listItem)) {
            return onKeyDown(event);
          }
          event.preventDefault();
          return Transforms.splitNodes(editor, {
            always: true,
            at: selection.focus,
            match: (node) => Editor.isBlock(editor, node) && editor.isDefaultElement(node)
          });
        } else if (isListItemElement(closestBlockElement)) {
          const [listItemStart, listItemEnd] = Editor.edges(editor, closestBlockPath);
          event.preventDefault();
          return Editor.withoutNormalizing(editor, () => {
            Transforms.wrapNodes(editor, editor.createDefaultElement([]), {
              match: (node) => Text.isText(node) || Element.isElement(node) && editor.isInline(node),
              at: {
                anchor: listItemStart,
                focus: listItemEnd
              }
            });
            const relative = Path.relative(selection.focus.path, closestBlockPath);
            Transforms.splitNodes(editor, {
              at: {
                path: [...closestBlockPath, 0, ...relative],
                offset: selection.focus.offset
              },
              always: true
            });
          });
        }
      }
      return onKeyDown(event);
    }
  });
  return editor;
};
export { withLists };
//# sourceMappingURL=withLists.js.map
