import { RicosCellSelection } from "../plugins/cellselection.js";
import { TableMap } from "../tablemap.js";
function isEmpty(cell) {
  const c = cell.content;
  return c.childCount === 1 && c.child(0).isTextblock && c.child(0).childCount === 0;
}
function cellsOverlapRectangle({ width, height, map }, rect) {
  let indexTop = rect.top * width + rect.left, indexLeft = indexTop;
  let indexBottom = (rect.bottom - 1) * width + rect.left, indexRight = indexTop + (rect.right - rect.left - 1);
  for (let i = rect.top; i < rect.bottom; i++) {
    if (rect.left > 0 && map[indexLeft] === map[indexLeft - 1] || rect.right < width && map[indexRight] === map[indexRight + 1]) {
      return true;
    }
    indexLeft += width;
    indexRight += width;
  }
  for (let i = rect.left; i < rect.right; i++) {
    if (rect.top > 0 && map[indexTop] === map[indexTop - width] || rect.bottom < height && map[indexBottom] === map[indexBottom + width]) {
      return true;
    }
    indexTop++;
    indexBottom++;
  }
  return false;
}
function cellAround($pos) {
  for (let d = $pos.depth - 1; d > 0; d--) {
    if ($pos.node(d).type.spec.tableRole === "row") {
      return $pos.node(0).resolve($pos.before(d + 1));
    }
  }
  return null;
}
function cellWrapping($pos) {
  for (let d = $pos.depth; d > 0; d--) {
    const role = $pos.node(d).type.spec.tableRole;
    if (role === "cell" || role === "header_cell") {
      return $pos.node(d);
    }
  }
  return null;
}
function cellNear($pos) {
  for (let after = $pos.nodeAfter, pos = $pos.pos; after; after = after.firstChild, pos++) {
    const role = after.type.spec.tableRole;
    if (role === "cell" || role === "header_cell") {
      return $pos.doc.resolve(pos);
    }
  }
  for (let before = $pos.nodeBefore, pos = $pos.pos; before; before = before.lastChild, pos--) {
    const role = before.type.spec.tableRole;
    if (role === "cell" || role === "header_cell") {
      return $pos.doc.resolve(pos - before.nodeSize);
    }
  }
}
function nextCell($pos, axis, dir) {
  const table = $pos.node(-1);
  const map = TableMap.get(table);
  const tableStart = $pos.start(-1);
  const moved = map.nextCell($pos.pos - tableStart, axis, dir);
  return moved === null ? null : $pos.node(0).resolve(tableStart + moved);
}
function isInTable(state) {
  const $head = state.selection.$head;
  for (let d = $head.depth; d > 0; d--) {
    if ($head.node(d).type.spec.tableRole === "row") {
      return true;
    }
  }
  return false;
}
function selectionCell(state) {
  const sel = state.selection;
  if ("$anchorCell" in sel && sel.$anchorCell) {
    return sel.$anchorCell.pos > sel.$headCell.pos ? sel.$anchorCell : sel.$headCell;
  } else if ("node" in sel && sel.node && sel.node.type.spec.tableRole === "cell") {
    return sel.$anchor;
  }
  const $cell = cellAround(sel.$head) || cellNear(sel.$head);
  if ($cell) {
    return $cell;
  }
  throw new RangeError(`No cell found around position ${sel.head}`);
}
function selectedRect(state) {
  const sel = state.selection;
  const $pos = selectionCell(state);
  const table = $pos.node(-1);
  const tableStart = $pos.start(-1);
  const map = TableMap.get(table);
  if (sel instanceof RicosCellSelection) {
    const rect = map.rectBetween(sel.$anchorCell.pos - tableStart, sel.$headCell.pos - tableStart);
    return { ...rect, tableStart, map, table };
  }
  const { col, row, colspan, rowspan } = map.findCell($pos.pos - tableStart);
  return {
    left: col,
    top: row,
    right: col + colspan,
    bottom: row + rowspan,
    tableStart,
    map,
    table
  };
}
function tableNodeTypes(schema) {
  let result = schema.cached.tableNodeTypes;
  if (!result) {
    result = schema.cached.tableNodeTypes = {};
    for (const name in schema.nodes) {
      if (Object.prototype.hasOwnProperty.call(schema.nodes, name)) {
        const type = schema.nodes[name], role = type.spec.tableRole;
        if (role) {
          result[role] = type;
        }
      }
    }
  }
  return result;
}
function columnIsHeader(map, table, col) {
  const headerCell = tableNodeTypes(table.type.schema).header_cell;
  for (let row = 0; row < map.height; row++) {
    if (table.nodeAt(map.map[col + row * map.width]).type !== headerCell) {
      return false;
    }
  }
  return true;
}
function rowIsHeader(map, table, row) {
  const headerCell = tableNodeTypes(table.type.schema).header_cell;
  for (let col = 0; col < map.width; col++) {
    if (table.nodeAt(map.map[col + row * map.width])?.type !== headerCell) {
      return false;
    }
  }
  return true;
}
function isHeaderEnabledByType(type, rect, types) {
  const cellPositions = rect.map.cellsInRect({
    left: 0,
    top: 0,
    right: type === "row" ? rect.map.width : 1,
    bottom: type === "column" ? rect.map.height : 1
  });
  let enabled = true;
  let spansCrossBoundary = false;
  for (let i = 0; i < cellPositions.length; i++) {
    const cell = rect.table.nodeAt(cellPositions[i]);
    if (!cell) {
      continue;
    }
    if (cell.type !== types.header_cell) {
      enabled = false;
    }
    if (type === "row" ? cell.attrs.rowspan > 1 : cell.attrs.colspan > 1) {
      spansCrossBoundary = true;
    }
  }
  return { enabled, spansCrossBoundary };
}
function getTableRectFromDoc(doc, tableStart) {
  const $pos = doc.resolve(tableStart + 1);
  const table = $pos.node(-1);
  const actualTableStart = $pos.start(-1);
  const map = TableMap.get(table);
  return {
    left: 0,
    right: map.width,
    top: 0,
    bottom: map.height,
    table,
    tableStart: actualTableStart,
    map
  };
}
export {
  cellAround,
  cellNear,
  cellWrapping,
  cellsOverlapRectangle,
  columnIsHeader,
  getTableRectFromDoc,
  isEmpty,
  isHeaderEnabledByType,
  isInTable,
  nextCell,
  rowIsHeader,
  selectedRect,
  selectionCell,
  tableNodeTypes
};
//# sourceMappingURL=queries.js.map
