"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var resolve_incremental_selection_exports = {};
__export(resolve_incremental_selection_exports, {
  resolveIncrementalSelection: () => resolveIncrementalSelection
});
module.exports = __toCommonJS(resolve_incremental_selection_exports);
var import_consts = require("./../../ricos-content/consts.js");
var import_plugin_types = require("./../../ricos-types/plugin-types.js");
var import_is_cell_selection = require("./../../_shared/is-cell-selection.js");
var import_tiptap = require("./../../tiptap/index.js");
var import_state = require("./../../tiptap/pm/state.js");
var import_tablemap = require("./../../plugin-table/tiptap/tablemap.js");
const resolveIncrementalSelection = (editor) => {
  const { state } = editor;
  const { selection, doc } = state;
  const { from, to } = selection;
  const $from = doc.resolve(from);
  const context = {
    selection,
    doc,
    $from,
    from,
    to
  };
  if (from === 0 && to === doc.content.size) {
    return null;
  }
  if (selection instanceof import_state.NodeSelection && selection.node.type.name === import_plugin_types.Node_Type.SMART_BLOCK_CELL) {
    const smartBlock = (0, import_tiptap.findParentNodeClosestToPos)(
      $from,
      (node) => node.type.name === import_plugin_types.Node_Type.SMART_BLOCK
    );
    if (smartBlock) {
      return { from: smartBlock.pos, to: smartBlock.pos + smartBlock.node.nodeSize, type: "node" };
    }
  }
  const initialDepth = $from.depth;
  const currentNodeStart = $from.start(initialDepth);
  const currentNodeEnd = $from.end(initialDepth);
  const selectionSpansBeyondCurrentNode = from < currentNodeStart || to > currentNodeEnd;
  const nodeIsEmpty = $from.node(initialDepth).isText && !$from.node(initialDepth).text;
  if (selectionSpansBeyondCurrentNode || nodeIsEmpty) {
    return selectAll(context);
  }
  const isCurrentNodeCard = $from.node(initialDepth).type.name === import_plugin_types.Node_Type.CARD;
  const isCurrentNodeFullySelected = isCurrentNodeCard ? isCardFullySelected(from, to, $from, initialDepth) : from === currentNodeStart && to === currentNodeEnd;
  const isCurrentNodeCardWrapper = isCardWrapper($from.node(initialDepth));
  if (!isCurrentNodeFullySelected && !isCurrentNodeCardWrapper) {
    return { from: currentNodeStart, to: currentNodeEnd, type: "text" };
  }
  const currentContext = findParentMostSelectedContext(context);
  const currentDepth = currentContext.$from.depth;
  const currentNode = currentContext.$from.node(currentDepth);
  const nodeType = currentNode.type.name;
  switch (nodeType) {
    // List-related nodes all use the same logic to find outermost list
    case import_plugin_types.Node_Type.LIST_ITEM:
    case import_plugin_types.Node_Type.COLLAPSIBLE_ITEM:
    case import_plugin_types.Node_Type.BULLETED_LIST:
    case import_plugin_types.Node_Type.CHECKBOX_LIST:
    case import_plugin_types.Node_Type.ORDERED_LIST:
    case import_plugin_types.Node_Type.COLLAPSIBLE_LIST:
    case import_plugin_types.Node_Type.COLLAPSIBLE_ITEM_TITLE:
    case import_plugin_types.Node_Type.COLLAPSIBLE_ITEM_BODY: {
      const selection2 = handleListNodeSelection(currentContext);
      if (selection2) {
        return selection2;
      }
      break;
    }
    // Table-related nodes use table selection logic
    case import_plugin_types.Node_Type.TABLE_CELL:
    case import_consts.TIPTAP_TABLE_HEADER_CELL_TYPE: {
      const selection2 = handleTableCellSelection(currentContext);
      if (selection2) {
        return selection2;
      }
      break;
    }
    // Smart block cell: select all smart block content
    case import_plugin_types.Node_Type.SMART_BLOCK_CELL: {
      const selection2 = handleSmartBlockCellSelection(currentContext);
      if (selection2) {
        return selection2;
      }
      break;
    }
    // Layout-related nodes use layout selection logic
    case import_plugin_types.Node_Type.LAYOUT:
    case import_plugin_types.Node_Type.LAYOUT_CELL: {
      const selection2 = handleLayoutSelection(currentContext);
      if (selection2) {
        return selection2;
      }
      break;
    }
    default:
      break;
  }
  if (currentDepth > 0) {
    return selectParentNode(currentContext);
  }
  return selectAll(context);
};
const PARENT_TAG_OFFSET = 1;
const isCardFullySelected = (from, to, $from, depth) => {
  const cardStart = $from.start(depth);
  const cardEnd = $from.end(depth);
  if (from - cardStart <= PARENT_TAG_OFFSET && cardEnd - to <= PARENT_TAG_OFFSET) {
    return true;
  }
  const card = $from.node(depth);
  let firstInnerCursor = null;
  let lastInnerCursor = null;
  card.descendants((node, offset) => {
    if (node.isTextblock) {
      const innerStart = cardStart + offset + 1;
      const innerEnd = cardStart + offset + node.nodeSize - 1;
      if (firstInnerCursor === null) {
        firstInnerCursor = innerStart;
      }
      lastInnerCursor = innerEnd;
    }
    return true;
  });
  return firstInnerCursor !== null && lastInnerCursor !== null && from <= firstInnerCursor && to >= lastInnerCursor;
};
const SKIP_TO_PARENT_NODES = [
  import_plugin_types.Node_Type.LIST_ITEM,
  // Skip to select parent list
  import_plugin_types.Node_Type.COLLAPSIBLE_ITEM_BODY,
  // Skip to select parent collapsible list
  import_plugin_types.Node_Type.LAYOUT_CELL
  // Skip to select parent layout
];
const getNodeBoundaries = (pos, nodeSize) => ({
  from: pos,
  to: pos + nodeSize
});
const isFullTableCellSelection = (selection, tableNode) => {
  if (!(0, import_is_cell_selection.isCellSelection)(selection)) {
    return false;
  }
  try {
    const tableMap = import_tablemap.TableMap.get(tableNode);
    const selectedRect = tableMap.rectBetween(
      selection.$anchorCell.pos - selection.$anchorCell.start(-1),
      selection.$headCell.pos - selection.$headCell.start(-1)
    );
    return selectedRect.left === 0 && selectedRect.right === tableMap.width && selectedRect.top === 0 && selectedRect.bottom === tableMap.height;
  } catch {
    return false;
  }
};
const selectAll = (context) => {
  const card = (0, import_tiptap.findParentNodeClosestToPos)(context.$from, (node) => node.type.name === import_plugin_types.Node_Type.CARD);
  if (card) {
    const cardContentStart = card.pos + PARENT_TAG_OFFSET;
    const cardContentEnd = card.pos + card.node.nodeSize - PARENT_TAG_OFFSET;
    const isCardContentSelected = Math.abs(context.from - cardContentStart) <= PARENT_TAG_OFFSET && Math.abs(context.to - cardContentEnd) <= PARENT_TAG_OFFSET;
    const isSelectionBeyondCard = context.from < cardContentStart || context.to > cardContentEnd;
    const isCardContentAdjusted = context.from > cardContentStart && context.to >= cardContentEnd - PARENT_TAG_OFFSET && context.to <= cardContentEnd;
    if (!isCardContentSelected && !isCardContentAdjusted && !isSelectionBeyondCard) {
      return { from: cardContentStart, to: cardContentEnd, type: "text" };
    }
  }
  return { from: 0, to: context.doc.content.size, type: "all" };
};
const findParentMostSelectedContext = (context) => {
  const { $from, from, to, doc } = context;
  let currentDepth = $from.depth;
  let selectionStart = from;
  let selectionEnd = to;
  while (currentDepth > 0) {
    const parentDepth = currentDepth - 1;
    const parentContentStart = $from.start(parentDepth);
    const parentContentEnd = $from.end(parentDepth);
    const startBoundaryDifference = Math.abs(selectionStart - parentContentStart);
    const endBoundaryDifference = Math.abs(selectionEnd - parentContentEnd);
    const isParentContentSelected = startBoundaryDifference <= PARENT_TAG_OFFSET && endBoundaryDifference <= PARENT_TAG_OFFSET;
    const parentNode = $from.node(parentDepth);
    const isSkipToParentNode = SKIP_TO_PARENT_NODES.includes(parentNode.type.name);
    const isCardParent = parentNode.type.name === import_plugin_types.Node_Type.CARD;
    const isCardWrapperParent = isCardWrapper(parentNode);
    if (isParentContentSelected && !isCardParent && !isCardWrapperParent || isSkipToParentNode) {
      currentDepth = parentDepth;
      selectionStart = parentContentStart;
      selectionEnd = parentContentEnd;
    } else {
      break;
    }
  }
  return {
    ...context,
    $from: doc.resolve(selectionStart),
    from: selectionStart,
    to: selectionEnd
  };
};
const isCardWrapper = (node) => node.type.name === import_consts.TIPTAP_CARD_HEADER_TYPE || node.type.name === import_consts.TIPTAP_CARD_CONTENT_TYPE || node.type.name === import_consts.TIPTAP_CARD_FOOTER_TYPE;
const selectParentNode = (context) => {
  const currentDepth = context.$from.depth;
  let parentDepth = currentDepth - 1;
  let parentNode = context.$from.node(parentDepth);
  while (parentDepth > 0 && isCardWrapper(parentNode)) {
    parentDepth -= 1;
    parentNode = context.$from.node(parentDepth);
  }
  const parentNodeStart = context.$from.start(parentDepth);
  const parentNodeEnd = context.$from.end(parentDepth);
  if (context.from > parentNodeStart || context.to < parentNodeEnd) {
    const isCardNode = parentNode.type.name === import_plugin_types.Node_Type.CARD;
    const selectionType = isCardNode ? "text" : parentNode.isBlock ? "node" : "text";
    if (selectionType === "node" && parentDepth > 0) {
      const parentPos = context.$from.before(parentDepth);
      const nodeBoundaries = getNodeBoundaries(parentPos, parentNode.nodeSize);
      return { ...nodeBoundaries, type: "node" };
    } else {
      return { from: parentNodeStart, to: parentNodeEnd, type: "text" };
    }
  }
  return selectAll(context);
};
const handleListNodeSelection = (context) => {
  const LIST_TYPES = [
    import_plugin_types.Node_Type.BULLETED_LIST,
    import_plugin_types.Node_Type.CHECKBOX_LIST,
    import_plugin_types.Node_Type.ORDERED_LIST,
    import_plugin_types.Node_Type.COLLAPSIBLE_LIST
  ];
  const findOutermostList = (selection) => {
    let currentList = null;
    let currentDepth = selection.$from.depth;
    while (currentDepth > 0) {
      const node = selection.$from.node(currentDepth);
      if (LIST_TYPES.includes(node.type.name)) {
        currentList = { node, pos: selection.$from.before(currentDepth) };
      }
      currentDepth--;
    }
    return currentList;
  };
  const outermostList = findOutermostList(context.selection);
  if (!outermostList) {
    return selectAll(context);
  }
  const { from: outermostListStart, to: outermostListEnd } = getNodeBoundaries(
    outermostList.pos,
    outermostList.node.nodeSize
  );
  const listContentStart = outermostList.pos + PARENT_TAG_OFFSET;
  const listContentEnd = outermostList.pos + outermostList.node.nodeSize - PARENT_TAG_OFFSET;
  if (context.from === listContentStart && context.to === listContentEnd) {
    return selectAll(context);
  }
  return { from: outermostListStart, to: outermostListEnd, type: "text" };
};
const handleTableCellSelection = (context) => {
  const table = (0, import_tiptap.findParentNodeClosestToPos)(
    context.$from,
    (node) => node.type.name === import_plugin_types.Node_Type.TABLE
  );
  if (!table) {
    return selectAll(context);
  }
  if (isFullTableCellSelection(context.selection, table.node)) {
    return selectAll(context);
  }
  const tableBoundaries = getNodeBoundaries(table.pos, table.node.nodeSize);
  return { ...tableBoundaries, type: "node" };
};
const handleLayoutSelection = (context) => {
  const layout = (0, import_tiptap.findParentNodeClosestToPos)(
    context.$from,
    (node) => node.type.name === import_plugin_types.Node_Type.LAYOUT
  );
  if (!layout) {
    return selectAll(context);
  }
  const layoutBoundaries = getNodeBoundaries(layout.pos, layout.node.nodeSize);
  if (context.from <= layoutBoundaries.from && context.to >= layoutBoundaries.to) {
    return selectAll(context);
  }
  const $layoutPos = context.doc.resolve(layout.pos);
  const layoutParentName = $layoutPos.parent.type.name;
  const isLayoutInCardWrapper = layoutParentName === import_consts.TIPTAP_CARD_HEADER_TYPE || layoutParentName === import_consts.TIPTAP_CARD_FOOTER_TYPE;
  if (isLayoutInCardWrapper) {
    return { ...layoutBoundaries, type: "node" };
  }
  return { ...layoutBoundaries, type: "text" };
};
const handleSmartBlockCellSelection = (context) => {
  const smartBlock = (0, import_tiptap.findParentNodeClosestToPos)(
    context.$from,
    (node) => node.type.name === import_plugin_types.Node_Type.SMART_BLOCK
  );
  if (!smartBlock) {
    return selectAll(context);
  }
  return {
    from: smartBlock.pos + PARENT_TAG_OFFSET,
    to: smartBlock.pos + smartBlock.node.nodeSize - PARENT_TAG_OFFSET,
    type: "text"
  };
};
//# sourceMappingURL=resolve-incremental-selection.js.map
