import { applyBorderEdit, extractCellPositions } from "../../borders/canonical-remap.js";
import { buildCellGrid, getCellAt } from "../../borders/edge-detection.js";
import { TableQuery } from "../table-query.js";
import { isRicosCellSelection } from "../utilities/is-selection-type.js";
const isOuterEdge = (cellData, side, tableWidth, tableHeight, isCellInSelection) => {
  const { row, col, rowspan, colspan } = cellData;
  switch (side) {
    case "top":
      return row === 0 || !isCellInSelection(row - 1, col);
    case "bottom":
      return row + rowspan >= tableHeight || !isCellInSelection(row + rowspan, col);
    case "left":
      return col === 0 || !isCellInSelection(row, col - 1);
    case "right":
      return col + colspan >= tableWidth || !isCellInSelection(row, col + colspan);
    default:
      return false;
  }
};
function prepareBorderContext(state) {
  const { selection } = state;
  const table = TableQuery.of(selection);
  if (!table || !isRicosCellSelection(selection)) {
    return null;
  }
  const tableNode = table.getNode();
  const tableStart = table.getStartPos();
  const allSelectedCells = [];
  selection.forEachCell((node, pos) => allSelectedCells.push({ node, pos }));
  return { tableNode, tableStart, allSelectedCells };
}
function prepareGridContext(state) {
  const ctx = prepareBorderContext(state);
  if (!ctx) {
    return null;
  }
  const { cells, width, height } = extractCellPositions(ctx.tableNode, ctx.tableStart);
  const selectedCellIds = /* @__PURE__ */ new Set();
  for (const { node } of ctx.allSelectedCells) {
    if (node.attrs.id) {
      selectedCellIds.add(node.attrs.id);
    }
  }
  const grid = buildCellGrid(cells, width, height);
  const isCellInSelection = (row, col) => {
    const cell = getCellAt(grid, row, col);
    return cell ? selectedCellIds.has(cell.node.attrs.id) : false;
  };
  return { ...ctx, cells, width, height, isCellInSelection };
}
function setCellBorderStyle(style, clear) {
  return (state, dispatch) => {
    const ctx = prepareBorderContext(state);
    if (!ctx) {
      return false;
    }
    if (!dispatch) {
      return true;
    }
    const tr = state.tr;
    applyBorderEdit(tr, ctx.tableNode, ctx.tableStart, ctx.allSelectedCells, null, style, clear);
    dispatch(tr);
    return true;
  };
}
const setCellBorderColor = (color) => setCellBorderStyle({ color }, color === void 0);
const setCellBorderWidth = (width) => setCellBorderStyle({ width }, false);
function setOutsiderCellsBorderStyle(style, clear) {
  return (state, dispatch) => {
    const ctx = prepareGridContext(state);
    if (!ctx) {
      return false;
    }
    if (!dispatch) {
      return true;
    }
    const sides = ["top", "bottom", "left", "right"];
    const outerEdgeCells = new Map(sides.map((s) => [s, []]));
    for (const { node, pos } of ctx.allSelectedCells) {
      const cellData = ctx.cells.find((c) => c.node.attrs.id === node.attrs.id);
      if (!cellData) {
        continue;
      }
      for (const side of sides) {
        if (isOuterEdge(cellData, side, ctx.width, ctx.height, ctx.isCellInSelection)) {
          outerEdgeCells.get(side).push({ node, pos });
        }
      }
    }
    const tr = state.tr;
    for (const side of sides) {
      const cellsForSide = outerEdgeCells.get(side);
      if (cellsForSide.length > 0) {
        const $pos = tr.doc.resolve(ctx.tableStart);
        const currentTable = $pos.node($pos.depth);
        if (currentTable?.type.spec.tableRole === "table") {
          applyBorderEdit(tr, currentTable, ctx.tableStart, cellsForSide, side, style, clear);
        }
      }
    }
    dispatch(tr);
    return true;
  };
}
const setOutsiderCellsBorderColor = (color) => setOutsiderCellsBorderStyle({ color }, color === void 0);
const setOutsiderCellsBorderWidth = (width) => setOutsiderCellsBorderStyle({ width }, false);
function setCellBorderBySideStyle(side, style, clear) {
  return (state, dispatch) => {
    const ctx = prepareGridContext(state);
    if (!ctx) {
      return false;
    }
    if (!dispatch) {
      return true;
    }
    const outerCells = [];
    for (const { node, pos } of ctx.allSelectedCells) {
      const cellData = ctx.cells.find((c) => c.node.attrs.id === node.attrs.id);
      if (!cellData) {
        continue;
      }
      if (isOuterEdge(cellData, side, ctx.width, ctx.height, ctx.isCellInSelection)) {
        outerCells.push({ node, pos });
      }
    }
    const tr = state.tr;
    if (outerCells.length > 0) {
      applyBorderEdit(tr, ctx.tableNode, ctx.tableStart, outerCells, side, style, clear);
    }
    dispatch(tr);
    return true;
  };
}
const setCellBorderColorBySide = (side, color) => setCellBorderBySideStyle(side, { color }, color === void 0);
const setCellBorderWidthBySide = (side, width) => setCellBorderBySideStyle(side, { width }, false);
function setInnerHorizontalCellsBorderStyle(style, clear) {
  return (state, dispatch) => {
    const ctx = prepareGridContext(state);
    if (!ctx) {
      return false;
    }
    if (!dispatch) {
      return true;
    }
    const innerCells = ctx.allSelectedCells.filter(({ node }) => {
      const cellData = ctx.cells.find((c) => c.node.attrs.id === node.attrs.id);
      return cellData && cellData.row > 0 && ctx.isCellInSelection(cellData.row - 1, cellData.col);
    });
    const tr = state.tr;
    if (innerCells.length > 0) {
      applyBorderEdit(tr, ctx.tableNode, ctx.tableStart, innerCells, "top", style, clear);
    }
    dispatch(tr);
    return true;
  };
}
const setInnerHorizontalCellsBorderColor = (color) => setInnerHorizontalCellsBorderStyle({ color }, color === void 0);
const setInnerHorizontalCellsBorderWidth = (width) => setInnerHorizontalCellsBorderStyle({ width }, false);
function setInnerVerticalCellsBorderStyle(style, clear) {
  return (state, dispatch) => {
    const ctx = prepareGridContext(state);
    if (!ctx) {
      return false;
    }
    if (!dispatch) {
      return true;
    }
    const innerCells = ctx.allSelectedCells.filter(({ node }) => {
      const cellData = ctx.cells.find((c) => c.node.attrs.id === node.attrs.id);
      return cellData && cellData.col > 0 && ctx.isCellInSelection(cellData.row, cellData.col - 1);
    });
    const tr = state.tr;
    if (innerCells.length > 0) {
      applyBorderEdit(tr, ctx.tableNode, ctx.tableStart, innerCells, "left", style, clear);
    }
    dispatch(tr);
    return true;
  };
}
const setInnerVerticalCellsBorderColor = (color) => setInnerVerticalCellsBorderStyle({ color }, color === void 0);
const setInnerVerticalCellsBorderWidth = (width) => setInnerVerticalCellsBorderStyle({ width }, false);
export {
  isOuterEdge,
  setCellBorderColor,
  setCellBorderColorBySide,
  setCellBorderWidth,
  setCellBorderWidthBySide,
  setInnerHorizontalCellsBorderColor,
  setInnerHorizontalCellsBorderWidth,
  setInnerVerticalCellsBorderColor,
  setInnerVerticalCellsBorderWidth,
  setOutsiderCellsBorderColor,
  setOutsiderCellsBorderWidth
};
//# sourceMappingURL=border.js.map
