"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.atTheBeginningOfBlock = atTheBeginningOfBlock;
Object.defineProperty(exports, "atTheBeginningOfDoc", {
  enumerable: true,
  get: function get() {
    return _atTheBeginningOfDoc.atTheBeginningOfDoc;
  }
});
exports.atTheEndOfBlock = atTheEndOfBlock;
Object.defineProperty(exports, "atTheEndOfDoc", {
  enumerable: true,
  get: function get() {
    return _atTheEndOfDoc.atTheEndOfDoc;
  }
});
exports.deleteSelectedRange = void 0;
Object.defineProperty(exports, "endPositionOfParent", {
  enumerable: true,
  get: function get() {
    return _endPositionOfParent.endPositionOfParent;
  }
});
Object.defineProperty(exports, "expandSelectionBounds", {
  enumerable: true,
  get: function get() {
    return _expandSelectionBounds.expandSelectionBounds;
  }
});
exports.expandToBlockRange = exports.expandSelectionToBlockRange = void 0;
exports.getSourceNodesFromSelectionRange = getSourceNodesFromSelectionRange;
Object.defineProperty(exports, "isMultiBlockRange", {
  enumerable: true,
  get: function get() {
    return _isMultiBlockRange.isMultiBlockRange;
  }
});
exports.isMultiBlockSelection = isMultiBlockSelection;
Object.defineProperty(exports, "isSelectionAtEndOfNode", {
  enumerable: true,
  get: function get() {
    return _isSelectionAtEndOfNode.isSelectionAtEndOfNode;
  }
});
Object.defineProperty(exports, "isSelectionAtStartOfNode", {
  enumerable: true,
  get: function get() {
    return _isSelectionAtStartOfNode.isSelectionAtStartOfNode;
  }
});
exports.selectionIsAtTheBeginningOfBlock = selectionIsAtTheBeginningOfBlock;
Object.defineProperty(exports, "startPositionOfParent", {
  enumerable: true,
  get: function get() {
    return _startPositionOfParent.startPositionOfParent;
  }
});
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _state = require("@atlaskit/editor-prosemirror/state");
var _utils = require("@atlaskit/editor-tables/utils");
var _utils2 = require("../utils");
var _endPositionOfParent = require("./endPositionOfParent");
var _selection = require("./gap-cursor/selection");
var _isMultiBlockRange = require("./isMultiBlockRange");
var _startPositionOfParent = require("./startPositionOfParent");
var _isSelectionAtStartOfNode = require("./isSelectionAtStartOfNode");
var _isSelectionAtEndOfNode = require("./isSelectionAtEndOfNode");
var _atTheEndOfDoc = require("./atTheEndOfDoc");
var _atTheBeginningOfDoc = require("./atTheBeginningOfDoc");
var _expandSelectionBounds = require("./expandSelectionBounds");
function atTheEndOfBlock(state) {
  var selection = state.selection;
  var $to = selection.$to;
  if (selection instanceof _selection.GapCursorSelection) {
    return false;
  }
  if (selection instanceof _state.NodeSelection && selection.node.isBlock) {
    return true;
  }
  return (0, _endPositionOfParent.endPositionOfParent)($to) === $to.pos + 1;
}
function atTheBeginningOfBlock(state) {
  var selection = state.selection;
  return selectionIsAtTheBeginningOfBlock(selection);
}
function selectionIsAtTheBeginningOfBlock(selection) {
  var $from = selection.$from;
  if (selection instanceof _selection.GapCursorSelection) {
    return false;
  }
  if (selection instanceof _state.NodeSelection && selection.node.isBlock) {
    return true;
  }
  return (0, _startPositionOfParent.startPositionOfParent)($from) === $from.pos;
}

/**
 * Delete what is selected in the given transaction.
 * @param tr the transaction to delete the selection from
 * @param selectionToUse optional selection to delete instead of the transaction's current selection
 * @returns the updated transaction
 */
var deleteSelectedRange = exports.deleteSelectedRange = function deleteSelectedRange(tr, selectionToUse) {
  var selection = selectionToUse || tr.selection;
  var from = selection.$from.pos;
  var to = selection.$to.pos;
  if (selection instanceof _state.TextSelection) {
    // Expand just the from position to the start of the block
    // This ensures entire paragraphs are deleted instead of just
    // the text content, which avoids leaving an empty line behind
    var expanded = expandToBlockRange(selection.$from, selection.$to);
    from = expanded.$from.pos;
  } else if ((0, _utils.isTableSelected)(selection)) {
    var table = (0, _utils.findTable)(selection);
    if (table) {
      from = table.pos;
      to = table.pos + table.node.nodeSize;
    }
  }
  tr.deleteRange(from, to);
  return tr;
};
var getDefaultPredicate = function getDefaultPredicate(_ref) {
  var nodes = _ref.nodes;
  var requiresFurtherExpansion = new Set([nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.listItem, nodes.taskItem, nodes.tableHeader, nodes.tableRow, nodes.tableCell, nodes.table, nodes.mediaGroup, nodes.mediaSingle]);
  return function (node) {
    return !requiresFurtherExpansion.has(node.type);
  };
};

/**
 * This expands the given $from and $to resolved positions to the block boundaries
 * spanning all nodes in the range up to the nearest common ancestor.
 *
 * By default, it will further expand the range when encountering specific node types
 * that require full block selection (like lists and tables). A custom predicate
 * can be provided to modify this behavior.
 *
 * @param $from The resolved start position
 * @param $to The resolved end position
 * @param predicate A predicate to determine if parent node is acceptable (see prosemirror-model/blockRange)
 * @returns An object containing the expanded $from and $to resolved positions
 */
var expandToBlockRange = exports.expandToBlockRange = function expandToBlockRange($from, $to) {
  var predicate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getDefaultPredicate($from.doc.type.schema);
  var range = $from.blockRange($to, predicate);
  if (!range) {
    return {
      $from: $from,
      $to: $to
    };
  }
  return {
    $from: $from.doc.resolve(range.start),
    $to: $to.doc.resolve(range.end),
    range: range
  };
};

/**
 * Expands a given selection to a block range, considering specific node types that require expansion.
 *
 * E.g. if the selection starts/ends at list items or table cells, the selection will be expanded
 * to encompass the entire list or table.
 *
 * Used mostly for block menu / drag handle related selections, where we want to ensure the selection
 * being acted upon covers the entire block range selected by the user.
 *
 * @param selection The selection to expand
 * @returns The expanded selection
 */
var expandSelectionToBlockRange = exports.expandSelectionToBlockRange = function expandSelectionToBlockRange(_ref2) {
  var $from = _ref2.$from,
    $to = _ref2.$to;
  return expandToBlockRange($from, $to);
};

/**
 * Determines if a selection contains multiple block nodes.
 */
function isMultiBlockSelection(selection) {
  var _expandSelectionToBlo = expandSelectionToBlockRange(selection),
    range = _expandSelectionToBlo.range;
  if (!range) {
    return false;
  }
  return (0, _isMultiBlockRange.isMultiBlockRange)(range);
}

/**
 * Extracts the source nodes from a selection range.
 *
 * This function expands the given selection to its block range boundaries and returns
 * an array of the nodes contained within that range. It handles special cases like
 * list nodes, where the slice positions are adjusted to include the list wrapper.
 *
 * @param tr - The transaction containing the document
 * @param selection - The selection to extract nodes from
 * @returns An array of ProseMirror nodes within the expanded selection range
 *
 * @example
 * ```typescript
 * const selection = tr.selection;
 * const nodes = getSourceNodesFromSelectionRange(tr, selection);
 * // nodes will contain all block-level nodes in the selection
 * ```
 */
function getSourceNodesFromSelectionRange(tr, selection) {
  var _expandSelectionToBlo2 = expandSelectionToBlockRange(selection),
    $from = _expandSelectionToBlo2.$from,
    $to = _expandSelectionToBlo2.$to;
  var selectedParent = $from.parent;
  var isList = (0, _utils2.isListNode)(selectedParent);
  var sliceStart = isList ? $from.pos - 1 : $from.pos;
  var sliceEnd = isList ? $to.pos + 1 : $to.pos;
  var slice = tr.doc.slice(sliceStart, sliceEnd);
  return (0, _toConsumableArray2.default)(slice.content.content);
}
// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export

// eslint-disable-next-line @atlaskit/editor/no-re-export