import { TIPTAP_TABLE_CELL_TYPE, TIPTAP_TABLE_HEADER_CELL_TYPE } from "./../../ricos-content/index.js";
import { resolveCssColor } from "./../../_shared/resolve-css-color.js";
import { resolveCellBordersPm } from "../borders/resolve-cell-borders.js";
import { getMinColumnWidthForPadding, normalizePadding } from "../defaults.js";
import { borderStyleToCSS } from "../tiptap/decorations/cell-edge-decorations.js";
import { RicosCellSelection } from "../tiptap/plugins/cellselection.js";
import { updateColumns } from "../tiptap/plugins/resize-utils.js";
import tableStyles from "../tiptap/plugins/table-scss.js";
import { TableQuery } from "../tiptap/table-query.js";
import { isRicosCellSelection } from "../tiptap/utilities/is-selection-type.js";
import { applyTableBorderChangeToTransaction } from "./apply-table-border-change.js";
class TableStylePreview {
  constructor(editor, capturedCells = null) {
    this.editor = editor;
    this.capturedCells = capturedCells;
    this.snapshots = /* @__PURE__ */ new Map();
  }
  get view() {
    return this.editor.view;
  }
  restore() {
    this.editor.commands?.setTableCellStylePreview?.(void 0);
    for (const [element, style] of this.snapshots) {
      if (style) {
        element.setAttribute("style", style);
      } else {
        element.removeAttribute("style");
      }
    }
    this.snapshots.clear();
  }
  /** Snapshots an element's inline style so `restore()` will undo any subsequent edits. */
  track(element) {
    if (!this.snapshots.has(element)) {
      this.snapshots.set(element, element.getAttribute("style") ?? "");
    }
  }
  resetToCaptured(element) {
    const original = this.snapshots.get(element);
    if (original) {
      element.setAttribute("style", original);
    } else {
      element.removeAttribute("style");
    }
  }
  applyPreviewStyle(element, apply) {
    this.track(element);
    this.resetToCaptured(element);
    apply(element.style);
  }
  getDomForCell(pos, id) {
    if (id) {
      const domById = [...this.view.dom.querySelectorAll("[data-node-id]")].find(
        (element) => element.getAttribute("data-node-id") === id
      );
      if (domById instanceof HTMLElement) {
        return domById;
      }
    }
    const dom = this.view.nodeDOM(pos);
    return dom instanceof HTMLElement ? dom : null;
  }
  getStateWithCellSelection() {
    const { state } = this.view;
    if (isRicosCellSelection(state.selection)) {
      return state;
    }
    if (!this.capturedCells?.length) {
      return null;
    }
    try {
      const cells = this.capturedCells.map(({ pos }) => state.doc.resolve(pos));
      return state.apply(state.tr.setSelection(new RicosCellSelection(cells, state.doc)));
    } catch (error) {
      if (false) {
        console.warn("[TableStylePreview] captured cell positions no longer resolve", error);
      }
      return null;
    }
  }
  getTableQuery() {
    const state = this.getStateWithCellSelection();
    return state ? TableQuery.of(state.selection) : null;
  }
  getTableNodeAndStart() {
    const table = this.getTableQuery();
    return table ? { node: table.getNode(), start: table.getStartPos() } : null;
  }
  getTableContainer() {
    const capturedCellContainer = this.capturedCells?.map(({ element }) => element?.closest("[data-table-container]")).find((element) => element instanceof HTMLElement);
    if (capturedCellContainer) {
      return capturedCellContainer;
    }
    const table = this.getTableQuery();
    if (!table) {
      return null;
    }
    const nodeDom = this.view.nodeDOM(table.getStartPos() - 1);
    if (nodeDom instanceof HTMLElement) {
      return nodeDom.dataset.tableContainer === "true" ? nodeDom : nodeDom.closest("[data-table-container]");
    }
    const domAtPos = this.view.domAtPos(table.getStartPos() - 1);
    const dom = domAtPos.node.childNodes[domAtPos.offset];
    return dom instanceof HTMLElement ? dom.dataset.tableContainer === "true" ? dom : dom.closest("[data-table-container]") : null;
  }
  getTableElement() {
    const container = this.getTableContainer();
    const table = container?.querySelector("table");
    return table instanceof HTMLTableElement ? table : null;
  }
  previewResolvedBorders(tableNode, tableStart, cellSpacing) {
    const resolvedBorders = resolveCellBordersPm(tableNode, {
      drawDefaultGrid: true,
      cellSpacing
    });
    const cellDecorations = [];
    tableNode.descendants((node, relativePos) => {
      if (node.type.name !== TIPTAP_TABLE_CELL_TYPE && node.type.name !== TIPTAP_TABLE_HEADER_CELL_TYPE) {
        return;
      }
      const cellId = node.attrs.id;
      if (!cellId) {
        return;
      }
      const borders = resolvedBorders.get(cellId);
      if (!borders) {
        return;
      }
      const pos = tableStart + relativePos;
      cellDecorations.push({
        from: pos,
        to: pos + node.nodeSize,
        style: `${borderStyleToCSS(borders)};--ricos-table-selection-overlay-z:0`
      });
    });
    if (cellDecorations.length > 0) {
      this.editor.commands.setTableCellStylePreview({ cellDecorations });
    }
  }
  forEachSelectedCell(callback) {
    if (this.capturedCells?.length) {
      for (const { element, id, pos } of this.capturedCells) {
        const dom = element?.isConnected ? element : this.getDomForCell(pos, id);
        if (dom) {
          callback(dom);
        }
      }
      return;
    }
    const { selection } = this.view.state;
    if (isRicosCellSelection(selection)) {
      selection.forEachCell((node, pos) => {
        const dom = this.getDomForCell(pos, node.attrs.id);
        if (dom) {
          callback(dom);
        }
      });
    }
  }
  previewCellBackground(color) {
    const resolvedColor = color ? resolveCssColor(color) : void 0;
    if (this.capturedCells?.length) {
      const cellDecorations = this.capturedCells.flatMap(({ pos }) => {
        const node = this.view.state.doc.nodeAt(pos);
        if (!node) {
          return [];
        }
        return [
          {
            from: pos,
            to: pos + node.nodeSize,
            className: resolvedColor ? tableStyles.backgroundColorPreview : void 0
          }
        ];
      });
      this.editor.commands.setTableCellStylePreview(
        cellDecorations.length > 0 ? {
          cellDecorations,
          rootStyle: resolvedColor ? {
            "--ricos-table-cell-background-color-preview": resolvedColor,
            "--ricos-table-preview-selection-color": resolvedColor,
            "--ricos-table-selection-overlay-z": "0"
          } : void 0
        } : void 0
      );
      return;
    }
    this.forEachSelectedCell((element) => {
      this.applyPreviewStyle(element, (style) => {
        if (resolvedColor) {
          style.backgroundColor = resolvedColor;
          style.setProperty("--ricos-table-preview-selection-color", resolvedColor);
        } else {
          style.removeProperty("background-color");
          style.removeProperty("--ricos-table-preview-selection-color");
        }
      });
    });
  }
  previewCellSpacing(spacing) {
    const container = this.getTableContainer();
    if (!container) {
      return;
    }
    const table = this.getTableNodeAndStart();
    if (table) {
      this.previewResolvedBorders(table.node, table.start, spacing);
    }
    this.applyPreviewStyle(container, (style) => {
      style.setProperty("--ricos-internal-table-gap", `${spacing}px`);
    });
  }
  previewCellPadding(padding) {
    const container = this.getTableContainer();
    if (!container) {
      return;
    }
    const normalized = normalizePadding(
      Array.isArray(padding) ? padding : [padding, padding, padding, padding],
      [10, 10, 10, 10]
    );
    this.applyPreviewStyle(container, (style) => {
      style.setProperty("--ricos-internal-table-cell-padding-top", `${normalized[0]}px`);
      style.setProperty(
        "--ricos-internal-table-cell-padding-right",
        `${normalized[1] ?? normalized[0]}px`
      );
      style.setProperty(
        "--ricos-internal-table-cell-padding-bottom",
        `${normalized[2] ?? normalized[0]}px`
      );
      style.setProperty(
        "--ricos-internal-table-cell-padding-left",
        `${normalized[3] ?? normalized[1] ?? normalized[0]}px`
      );
    });
    const tableInfo = this.getTableNodeAndStart();
    const tableElement = this.getTableElement();
    const colgroup = tableElement?.querySelector("colgroup");
    if (!tableInfo || !tableElement || !colgroup) {
      return;
    }
    const previewTableNode = tableInfo.node.type.create(
      {
        ...tableInfo.node.attrs,
        tableData: {
          ...tableInfo.node.attrs.tableData,
          cellPadding: normalized
        }
      },
      tableInfo.node.content,
      tableInfo.node.marks
    );
    this.track(tableElement);
    for (const col of Array.from(colgroup.children)) {
      if (col instanceof HTMLElement) {
        this.track(col);
      }
    }
    updateColumns({
      node: previewTableNode,
      colgroup,
      table: tableElement,
      cellMinWidth: getMinColumnWidthForPadding(normalized),
      commands: this.editor.commands,
      shouldUpdateState: false
    });
  }
  previewBorder(scope, change) {
    const state = this.getStateWithCellSelection();
    if (!state) {
      return;
    }
    const tr = state.tr;
    if (!applyTableBorderChangeToTransaction(tr, state, scope, change)) {
      return;
    }
    if (!tr.docChanged) {
      return;
    }
    const previewState = state.apply(tr);
    const previewTable = TableQuery.of(previewState.selection);
    if (!previewTable) {
      return;
    }
    const tableNode = previewTable.getNode();
    const cellSpacing = tableNode.attrs.tableData?.cellSpacing ?? 0;
    const tableStart = previewTable.getStartPos();
    this.previewResolvedBorders(tableNode, tableStart, cellSpacing);
  }
}
const createTableStylePreview = (editor, capturedCells = null) => new TableStylePreview(editor, capturedCells);
export {
  TableStylePreview,
  createTableStylePreview
};
//# sourceMappingURL=table-style-preview.js.map
