import { Editor, Transforms, Text, Element, Path, Range, Point, Node } from "slate";
import { ContemberEditor } from "../../../ContemberEditor/index.js";
import { tableCellElementPlugin, isTableCellElement } from "./TableCellElement.js";
import { tableElementPlugin, isTableElement, getTableElementRowCount, getTableElementColumnCount } from "./TableElement.js";
import { tableRowElementPlugin, isTableRowElement } from "./TableRowElement.js";
import { getTableCellCoordinates, selectTableCellContents } from "./TableElementSelection.js";
const withTables = (editor) => {
  const {
    deleteForward,
    deleteBackward,
    deleteFragment,
    insertBreak,
    onKeyDown
  } = editor;
  editor.registerElement(tableElementPlugin);
  editor.registerElement(tableCellElementPlugin);
  editor.registerElement(tableRowElementPlugin);
  Object.assign(editor, {
    insertBreak: () => {
      const closestBlockEntry = ContemberEditor.closestBlockEntry(editor);
      if (closestBlockEntry && isTableCellElement(closestBlockEntry[0])) {
        const selection = editor.selection;
        const [, closestBlockPath] = closestBlockEntry;
        const [cellStart, cellEnd] = Editor.edges(editor, closestBlockPath);
        if (!selection) {
          return insertBreak();
        }
        return Editor.withoutNormalizing(editor, () => {
          Transforms.wrapNodes(editor, editor.createDefaultElement([]), {
            at: {
              anchor: cellStart,
              focus: cellEnd
            },
            match: (node) => Text.isText(node) || Element.isElement(node) && editor.isInline(node)
          });
          const relative = Path.relative(selection.focus.path, closestBlockPath);
          Transforms.splitNodes(editor, {
            at: {
              path: [...closestBlockPath, 0, ...relative],
              offset: selection.focus.offset
            },
            always: true
          });
        });
      }
      insertBreak();
    },
    deleteBackward: (unit) => {
      const selection = editor.selection;
      if (selection && Range.isCollapsed(selection)) {
        const closestBlockEntry = ContemberEditor.closestBlockEntry(editor);
        if (closestBlockEntry && isTableCellElement(closestBlockEntry[0]) && Point.equals(selection.focus, Editor.start(editor, closestBlockEntry[1]))) {
          return;
        }
      }
      deleteBackward(unit);
    },
    deleteForward: (unit) => {
      const selection = editor.selection;
      if (selection && Range.isCollapsed(selection)) {
        const closestBlockEntry = ContemberEditor.closestBlockEntry(editor);
        if (closestBlockEntry && isTableCellElement(closestBlockEntry[0]) && Point.equals(selection.focus, Editor.end(editor, closestBlockEntry[1]))) {
          return;
        }
      }
      deleteForward(unit);
    },
    deleteFragment: () => {
      const selection = editor.selection;
      if (!selection || Range.isCollapsed(selection)) {
        return deleteFragment();
      }
      const lowestCommonAncestorPath = Path.common(selection.anchor.path, selection.focus.path);
      const [lowestCommonAncestor] = Editor.node(editor, lowestCommonAncestorPath);
      if (isTableElement(lowestCommonAncestor) || isTableRowElement(lowestCommonAncestor)) {
        return;
      }
      deleteFragment();
    },
    onKeyDown: (event) => {
      const selection = editor.selection;
      if (!selection || !(event.key === "Tab" || event.key === "ArrowUp" || event.key === "ArrowRight" || event.key === "ArrowDown" || event.key === "ArrowLeft")) {
        return onKeyDown(event);
      }
      const closestBlockEntry = ContemberEditor.closestBlockEntry(editor, { at: selection });
      if (!closestBlockEntry) {
        return onKeyDown(event);
      }
      let cellElement;
      let cellPath;
      if (!isTableCellElement(closestBlockEntry[0])) {
        const parent = Node.parent(editor, closestBlockEntry[1]);
        if (Element.isElement(closestBlockEntry[0]) && editor.isDefaultElement(closestBlockEntry[0]) && isTableCellElement(parent)) {
          cellElement = parent;
          cellPath = Path.parent(closestBlockEntry[1]);
        } else {
          return onKeyDown(event);
        }
      } else {
        [cellElement, cellPath] = closestBlockEntry;
      }
      if (cellPath.length < 3) {
        return onKeyDown(event);
      }
      const [rowIndex, columnIndex] = getTableCellCoordinates(editor, cellElement);
      const tablePath = cellPath.slice(0, -2);
      const tableElement = Node.get(editor, tablePath);
      const rowCount = getTableElementRowCount(tableElement);
      const columnCount = getTableElementColumnCount(tableElement);
      if (rowCount === 0 || columnCount === 0) {
        return;
      }
      const moveSelectionBeforeTable = () => {
        const pointBeforeTable = Editor.before(editor, tablePath);
        if (!pointBeforeTable) {
          return onKeyDown(event);
        }
        event.preventDefault();
        return Transforms.select(editor, pointBeforeTable);
      };
      const moveSelectionAfterTable = () => {
        const pointAfterTable = Editor.after(editor, tablePath);
        if (!pointAfterTable) {
          return onKeyDown(event);
        }
        event.preventDefault();
        return Transforms.select(editor, pointAfterTable);
      };
      if (event.key === "Tab") {
        if (event.shiftKey) {
          if (columnIndex > 0) {
            event.preventDefault();
            return selectTableCellContents(editor, tablePath, rowIndex, columnIndex - 1);
          } else if (columnIndex === 0) {
            if (rowIndex > 0) {
              event.preventDefault();
              return selectTableCellContents(editor, tablePath, rowIndex - 1, columnCount - 1);
            }
            return moveSelectionBeforeTable();
          }
        } else {
          if (columnIndex < columnCount - 1) {
            event.preventDefault();
            return selectTableCellContents(editor, tablePath, rowIndex, columnIndex + 1);
          } else if (columnIndex === columnCount - 1) {
            if (rowIndex < rowCount - 1) {
              event.preventDefault();
              return selectTableCellContents(editor, tablePath, rowIndex + 1, 0);
            } else if (rowIndex === rowCount - 1) {
              return moveSelectionAfterTable();
            }
          }
        }
      }
      if (event.key === "ArrowLeft") {
        if (!Range.isCollapsed(selection)) {
          return onKeyDown(event);
        }
        if (Point.equals(selection.focus, Editor.start(editor, cellPath))) {
          if (columnIndex > 0) {
            event.preventDefault();
            return Transforms.select(editor, Editor.end(editor, [...tablePath, rowIndex, columnIndex - 1]));
          } else if (columnIndex === 0) {
            if (rowIndex > 0) {
              event.preventDefault();
              return Transforms.select(editor, Editor.end(editor, [...tablePath, rowIndex - 1, columnCount - 1]));
            }
            return moveSelectionBeforeTable();
          }
        }
      } else if (event.key === "ArrowRight") {
        if (!Range.isCollapsed(selection)) {
          return onKeyDown(event);
        }
        if (Point.equals(selection.focus, Editor.end(editor, cellPath))) {
          if (columnIndex < columnCount - 1) {
            event.preventDefault();
            return Transforms.select(editor, Editor.start(editor, [...tablePath, rowIndex, columnIndex + 1]));
          } else if (columnIndex === columnCount - 1) {
            if (rowIndex < rowCount - 1) {
              event.preventDefault();
              return Transforms.select(editor, Editor.start(editor, [...tablePath, rowIndex + 1, 0]));
            } else if (rowIndex === rowCount - 1) {
              return moveSelectionAfterTable();
            }
          }
        }
      } else if (event.key === "ArrowUp" || event.key === "ArrowDown") {
        const withinDefault = editor.isDefaultElement(closestBlockEntry[0]);
        if (withinDefault) {
          const relative = Path.relative(closestBlockEntry[1], cellPath);
          const defaultIndex = relative[0];
          if (event.key === "ArrowUp" && defaultIndex !== 0 || event.key === "ArrowDown" && defaultIndex !== cellElement.children.length - 1) {
            return onKeyDown(event);
          }
        }
        if (event.key === "ArrowUp") {
          if (rowIndex > 0) {
            event.preventDefault();
            const rowAboveEndPoint = Editor.end(editor, [...tablePath, rowIndex - 1, columnIndex]);
            if (!Range.isCollapsed(selection)) {
              return Transforms.select(editor, rowAboveEndPoint);
            }
            const minOffset = Math.min(selection.focus.offset, rowAboveEndPoint.offset);
            return Transforms.select(editor, {
              path: rowAboveEndPoint.path,
              offset: minOffset
            });
          }
          return moveSelectionBeforeTable();
        } else if (event.key === "ArrowDown") {
          if (rowIndex < rowCount - 1) {
            event.preventDefault();
            const rowBelowStatPoint = Editor.start(editor, [...tablePath, rowIndex + 1, columnIndex]);
            if (!Range.isCollapsed(selection)) {
              return Transforms.select(editor, rowBelowStatPoint);
            }
            const [rowBelowStatPointNode] = Editor.node(editor, rowBelowStatPoint);
            return Transforms.select(editor, {
              path: rowBelowStatPoint.path,
              offset: Math.min(selection.focus.offset, rowBelowStatPointNode.text.length)
            });
          }
          return moveSelectionAfterTable();
        }
      }
      onKeyDown(event);
    }
  });
  return editor;
};
export { withTables };
//# sourceMappingURL=withTables.js.map
