import { TIPTAP_TABLE_TYPE } from "./../../ricos-content/index.js";
import { Node_Type } from "./../../ricos-schema/next-schema/index.js";
import { callOrReturn, getExtensionField } from "./../../tiptap/index.js";
import { Plugin, PluginKey } from "./../../tiptap/pm/state.js";
import { Decoration, DecorationSet } from "./../../tiptap/pm/view.js";
import { createRicosNodeExtension } from "./../../plugin-commons/index.js";
import { CELL_MANUAL_MIN_WIDTH, RESIZE_HANDLE_SIZE, ROW_RESIZE_HANDLE_SIZE } from "../consts.js";
import {
  setCellBorderColor,
  setCellBorderColorBySide,
  setCellBorderWidth,
  setCellBorderWidthBySide,
  setInnerHorizontalCellsBorderColor,
  setInnerHorizontalCellsBorderWidth,
  setInnerVerticalCellsBorderColor,
  setInnerVerticalCellsBorderWidth,
  setOutsiderCellsBorderColor,
  setOutsiderCellsBorderWidth
} from "./commands/border.js";
import {
  addColumnAtIndex,
  addRowAtIndex,
  clearCell,
  distributeColumns,
  distributeRows,
  insertTable,
  setCellAttribute,
  setCellPadding,
  setCellSpacing,
  setEditCell,
  setTableAltText,
  setTableRowHeight,
  toggleTableAttribute,
  updateCellAttribute
} from "./commands/cell-attributes.js";
import { fixTables } from "./commands/fix.js";
import {
  addColumnAfterWithBorders,
  addColumnBeforeWithBorders,
  addRowAfterWithBorders,
  addRowBeforeWithBorders,
  deleteColumnWithBorders,
  deleteRowWithBorders,
  deleteTable,
  mergeCellsWithBorders,
  splitCellWithBorders,
  toggleHeaderColumnCmd,
  toggleHeaderRowCmd
} from "./commands/mutations.js";
import { goToNextCell } from "./commands/navigation.js";
import { moveColumns, moveRows, reorderColumns, reorderRows } from "./commands/reorder.js";
import {
  deleteRowAtIndex,
  selectColumnAtIndex,
  selectColumnCmd,
  selectColumns,
  selectRowAtIndex,
  selectRowCmd,
  selectRows,
  selectWholeTable,
  setCellSelection
} from "./commands/selection.js";
import {
  TableView,
  cellEdgePlugin,
  columnResizingPlugin,
  handleDraggingPlugin,
  rowResizingPlugin,
  tableEditingPlugin
} from "./plugins/index.js";
import { keyboardShortcuts, maybeToggleEditMode } from "./utilities/keyboard-shortcuts.js";
const TABLE_SUPPORTED_QUICK_ACTIONS = [
  Node_Type.PARAGRAPH,
  Node_Type.HEADING,
  Node_Type.BULLETED_LIST,
  Node_Type.ORDERED_LIST,
  Node_Type.CHECKBOX_LIST,
  Node_Type.BLOCKQUOTE,
  Node_Type.AUDIO,
  Node_Type.FILE,
  Node_Type.IMAGE,
  Node_Type.VIDEO,
  Node_Type.GIF,
  Node_Type.DIVIDER,
  Node_Type.CODE_BLOCK,
  Node_Type.HTML,
  Node_Type.LINK_PREVIEW,
  Node_Type.APP_EMBED,
  Node_Type.BUTTON,
  Node_Type.EMBED,
  Node_Type.SHAPE
];
const TABLE_CELL_STYLE_PREVIEW_PLUGIN_KEY = new PluginKey(
  "tableCellStylePreview"
);
const PREVIEW_ROOT_STYLE_NAMES = [
  "--ricos-table-cell-background-color-preview",
  "--ricos-table-preview-selection-color",
  "--ricos-table-selection-overlay-z"
];
const syncTableCellStylePreview = (view) => {
  const rootStyle = TABLE_CELL_STYLE_PREVIEW_PLUGIN_KEY.getState(view.state)?.rootStyle ?? {};
  for (const name of PREVIEW_ROOT_STYLE_NAMES) {
    const value = rootStyle[name];
    if (value) {
      view.dom.style.setProperty(name, value);
    } else {
      view.dom.style.removeProperty(name);
    }
  }
};
const tableCellStylePreviewPlugin = () => new Plugin({
  key: TABLE_CELL_STYLE_PREVIEW_PLUGIN_KEY,
  state: {
    init() {
      return { cellDecorations: [] };
    },
    apply(tr, value) {
      const preview = tr.getMeta(TABLE_CELL_STYLE_PREVIEW_PLUGIN_KEY);
      return preview === void 0 ? value : preview;
    }
  },
  props: {
    decorations(state) {
      const preview = TABLE_CELL_STYLE_PREVIEW_PLUGIN_KEY.getState(state);
      const cellDecorations = preview?.cellDecorations ?? [];
      if (cellDecorations.length === 0) {
        return null;
      }
      return DecorationSet.create(
        state.doc,
        cellDecorations.map(
          ({ className, from, style, to }) => Decoration.node(from, to, {
            ...className ? { class: className } : {},
            ...style ? { style } : {}
          })
        )
      );
    }
  },
  view(view) {
    syncTableCellStylePreview(view);
    return {
      update(updatedView) {
        syncTableCellStylePreview(updatedView);
      },
      destroy() {
        for (const name of PREVIEW_ROOT_STYLE_NAMES) {
          view.dom.style.removeProperty(name);
        }
      }
    };
  }
});
const tableExtension = createRicosNodeExtension({
  groups: ["shortcuts-enabled", "footer-disabled"],
  type: "html-node",
  reconfigure: (config, _extensions, _props, settings, services) => ({
    ...config,
    addOptions: () => ({
      services,
      ...settings,
      View: TableView
    })
  }),
  name: TIPTAP_TABLE_TYPE,
  createExtensionConfig() {
    return {
      name: this.name,
      group: "block collapsibleListItemBodyContent",
      selectable: true,
      isolating: true,
      draggable: true,
      content: "TABLE_ROW+",
      supportedQuickActions: TABLE_SUPPORTED_QUICK_ACTIONS,
      tableRole: "table",
      priority: 101,
      contentDOM: document.createElement("tbody"),
      addAttributes: () => ({
        containerData: null,
        dimensions: {
          default: null,
          parseHTML: (element) => {
            const dimensionsAttr = element.getAttribute("data-dimensions");
            if (!dimensionsAttr) {
              return null;
            }
            try {
              return JSON.parse(dimensionsAttr);
            } catch {
              return null;
            }
          },
          renderHTML: (attributes) => {
            if (!attributes.dimensions) {
              return {};
            }
            return { "data-dimensions": JSON.stringify(attributes.dimensions) };
          }
        },
        header: null,
        edgeMap: null,
        tableData: {
          default: null,
          parseHTML: (element) => {
            const style = element.getAttribute("style");
            if (!style) {
              return null;
            }
            const result = {};
            const borderSpacingMatch = style.match(/border-spacing:\s*(\d+)px/);
            if (borderSpacingMatch) {
              result.cellSpacing = parseInt(borderSpacingMatch[1], 10);
            }
            const cellPaddingMatch = style.match(/--ricos-table-cell-padding:\s*([^;]+)/);
            if (cellPaddingMatch) {
              const paddingValues = cellPaddingMatch[1].trim().split(/\s+/).map((v) => parseInt(v, 10)).filter((v) => !isNaN(v));
              if (paddingValues.length > 0) {
                result.cellPadding = paddingValues;
              }
            }
            return Object.keys(result).length > 0 ? result : null;
          },
          renderHTML: (attributes) => {
            if (!attributes.tableData) {
              return {};
            }
            const styles = [];
            const tableData = attributes.tableData;
            if (typeof tableData.cellSpacing === "number") {
              styles.push(`border-spacing: ${tableData.cellSpacing}px`);
            }
            if (Array.isArray(tableData.cellPadding) && tableData.cellPadding.length > 0) {
              styles.push(`--ricos-table-cell-padding: ${tableData.cellPadding.join(" ")}`);
            }
            return styles.length > 0 ? { style: styles.join("; ") } : {};
          }
        }
      }),
      parseHTML() {
        return [{ tag: "table" }];
      },
      renderHTML({ HTMLAttributes }) {
        return ["table", { ...HTMLAttributes }, ["tbody", 0]];
      },
      addProseMirrorPlugins() {
        const isMobile = this.options.services?.context?.isMobile;
        return [
          ...!isMobile ? [
            columnResizingPlugin({
              editor: this.editor,
              minColumnWidth: CELL_MANUAL_MIN_WIDTH
            }),
            rowResizingPlugin({ editor: this.editor }),
            handleDraggingPlugin({ editor: this.editor })
          ] : [],
          tableEditingPlugin({ editor: this.editor, isMobile }),
          cellEdgePlugin(),
          tableCellStylePreviewPlugin()
        ];
      },
      extendNodeSchema(extension) {
        const context = {
          name: extension.name,
          options: extension.options,
          storage: extension.storage
        };
        return {
          tableRole: callOrReturn(getExtensionField(extension, "tableRole", context))
        };
      },
      addNodeView() {
        const isMobile = this.options.services?.context?.isMobile;
        return ({ node, editor, getPos }) => new TableView(
          node,
          editor,
          getPos,
          {
            columnResizeHandleWidth: RESIZE_HANDLE_SIZE,
            rowResizeHandleHeight: ROW_RESIZE_HANDLE_SIZE
          },
          isMobile
        );
      },
      addCommands() {
        return {
          setTableCellStylePreview: (preview) => ({ tr, dispatch }) => {
            dispatch?.(
              tr.setMeta(TABLE_CELL_STYLE_PREVIEW_PLUGIN_KEY, preview ?? { cellDecorations: [] })
            );
            return true;
          },
          insertTable: (opts) => ({ state, dispatch }) => insertTable(opts)(state, dispatch),
          addColumnBefore: () => ({ state, dispatch }) => addColumnBeforeWithBorders()(state, dispatch),
          addColumnAfter: () => ({ state, dispatch }) => addColumnAfterWithBorders()(state, dispatch),
          addColumnAtIndex: (index) => ({ state, dispatch }) => addColumnAtIndex(index)(state, dispatch),
          deleteColumn: () => ({ state, dispatch }) => deleteColumnWithBorders()(state, dispatch),
          addRowBefore: () => ({ state, dispatch }) => addRowBeforeWithBorders()(state, dispatch),
          addRowAfter: () => ({ state, dispatch }) => addRowAfterWithBorders()(state, dispatch),
          addRowAtIndex: (index) => ({ state, dispatch }) => addRowAtIndex(index)(state, dispatch),
          deleteRow: () => ({ state, dispatch }) => deleteRowWithBorders()(state, dispatch),
          deleteTable: () => ({ state, dispatch }) => deleteTable(state, dispatch),
          mergeCells: () => ({ state, dispatch }) => mergeCellsWithBorders()(state, dispatch),
          splitCell: () => ({ state, dispatch }) => splitCellWithBorders()(state, dispatch),
          toggleHeaderColumn: () => ({ state, dispatch }) => toggleHeaderColumnCmd()(state, dispatch),
          toggleHeaderRow: () => ({ state, dispatch }) => toggleHeaderRowCmd()(state, dispatch),
          mergeOrSplit: () => ({ state, dispatch }) => {
            if (mergeCellsWithBorders()(state, dispatch)) {
              return true;
            }
            return splitCellWithBorders()(state, dispatch);
          },
          setCellAttribute: (name, value) => ({ state, dispatch }) => setCellAttribute(name, value)(state, dispatch),
          updateCellAttribute: (name, value) => ({ state, dispatch }) => updateCellAttribute(name, value)(state, dispatch),
          toggleTableAttribute: (name) => ({ state, dispatch }) => toggleTableAttribute(name)(state, dispatch),
          setTableAltText: (text) => ({ state, dispatch }) => setTableAltText(text)(state, dispatch),
          goToNextCell: () => ({ state, dispatch }) => goToNextCell(1)(state, dispatch),
          goToPreviousCell: () => ({ state, dispatch }) => goToNextCell(-1)(state, dispatch),
          fixTables: () => ({ state, dispatch }) => {
            if (dispatch) {
              fixTables(state);
            }
            return true;
          },
          setCellSelection: (pos) => ({ state, dispatch }) => setCellSelection(pos)(state, dispatch),
          selectColumnAtIndex: (index) => ({ state, dispatch }) => selectColumnAtIndex(index)(state, dispatch),
          selectColumn: () => ({ state, dispatch }) => selectColumnCmd()(state, dispatch),
          selectRowAtIndex: (index) => ({ state, dispatch }) => selectRowAtIndex(index)(state, dispatch),
          selectRow: () => ({ state, dispatch }) => selectRowCmd()(state, dispatch),
          selectRows: (fromRow, toRow, tablePos) => ({ state, dispatch }) => selectRows(fromRow, toRow, tablePos)(state, dispatch),
          selectColumns: (fromCol, toCol, tablePos) => ({ state, dispatch }) => selectColumns(fromCol, toCol, tablePos)(state, dispatch),
          deleteRowAtIndex: (index) => ({ state, dispatch }) => deleteRowAtIndex(index)(state, dispatch),
          selectWholeTable: () => ({ state, dispatch }) => selectWholeTable()(state, dispatch),
          setTableRowHeight: (height, pos, node) => ({ state, dispatch }) => setTableRowHeight(height, pos, node)(state, dispatch),
          distributeRows: () => ({ state, dispatch }) => distributeRows()(state, dispatch),
          distributeColumns: () => ({ state, dispatch }) => distributeColumns()(state, dispatch),
          setEditCell: () => ({ state, dispatch }) => setEditCell()(state, dispatch),
          clearCell: () => ({ state, dispatch }) => clearCell()(state, dispatch),
          setCellBorderColor: (color) => ({ state, dispatch }) => setCellBorderColor(color)(state, dispatch),
          setOutsiderCellsBorderColor: (color) => ({ state, dispatch }) => setOutsiderCellsBorderColor(color)(state, dispatch),
          setCellBorderWidth: (width) => ({ state, dispatch }) => setCellBorderWidth(width)(state, dispatch),
          setOutsiderCellsBorderWidth: (width) => ({ state, dispatch }) => setOutsiderCellsBorderWidth(width)(state, dispatch),
          setCellBorderColorBySide: (side, color) => ({ state, dispatch }) => setCellBorderColorBySide(side, color)(state, dispatch),
          setCellBorderWidthBySide: (side, width) => ({ state, dispatch }) => setCellBorderWidthBySide(side, width)(state, dispatch),
          setInnerHorizontalCellsBorderColor: (color) => ({ state, dispatch }) => setInnerHorizontalCellsBorderColor(color)(state, dispatch),
          setInnerHorizontalCellsBorderWidth: (width) => ({ state, dispatch }) => setInnerHorizontalCellsBorderWidth(width)(state, dispatch),
          setInnerVerticalCellsBorderColor: (color) => ({ state, dispatch }) => setInnerVerticalCellsBorderColor(color)(state, dispatch),
          setInnerVerticalCellsBorderWidth: (width) => ({ state, dispatch }) => setInnerVerticalCellsBorderWidth(width)(state, dispatch),
          setCellSpacing: (spacing) => ({ state, dispatch }) => setCellSpacing(spacing)(state, dispatch),
          setCellPadding: (padding) => ({ state, dispatch }) => setCellPadding(padding)(state, dispatch),
          reorderRows: (from, to) => ({ state, dispatch }) => reorderRows(from, to)(state, dispatch),
          reorderColumns: (from, to) => ({ state, dispatch }) => reorderColumns(from, to)(state, dispatch),
          moveColumns: (direction) => ({ state, dispatch, view }) => moveColumns(direction)(state, dispatch, view),
          moveRows: (direction) => ({ state, dispatch, view }) => moveRows(direction)(state, dispatch, view)
        };
      },
      addKeyboardShortcuts() {
        const newLine = maybeToggleEditMode;
        const tiptapKeyboardShortcuts = keyboardShortcuts;
        const newLineShortcuts = [];
        this.options.services.shortcuts.shortcuts.forEach((shortcut) => {
          if (shortcut.shortcut.name === "NewLine") {
            newLineShortcuts.push(shortcut);
          }
        });
        newLineShortcuts.forEach((newLineShortcut) => {
          const modifier = newLineShortcut.keys.macOs.modifiers[0];
          const key = newLineShortcut.keys.macOs.key;
          const shortcutKey = modifier ? `${modifier}-${key}` : key;
          tiptapKeyboardShortcuts[shortcutKey] = newLine;
        });
        return tiptapKeyboardShortcuts;
      }
    };
  }
});
export {
  tableExtension
};
//# sourceMappingURL=table-extension.js.map
