import { FloatHorizontalRange } from "../../view/renderingContext.mjs";
class RangeUtil {
  static _createRange() {
    if (!this._handyReadyRange) {
      this._handyReadyRange = document.createRange();
    }
    return this._handyReadyRange;
  }
  static _detachRange(range, endNode) {
    range.selectNodeContents(endNode);
  }
  static _readClientRects(startElement, startOffset, endElement, endOffset, endNode) {
    const range = this._createRange();
    try {
      range.setStart(startElement, startOffset);
      range.setEnd(endElement, endOffset);
      return range.getClientRects();
    } catch (e) {
      return null;
    } finally {
      this._detachRange(range, endNode);
    }
  }
  static _mergeAdjacentRanges(ranges) {
    if (ranges.length === 1) {
      return ranges;
    }
    ranges.sort(FloatHorizontalRange.compare);
    const result = [];
    let resultLen = 0;
    let prev = ranges[0];
    for (let i = 1, len = ranges.length; i < len; i++) {
      const range = ranges[i];
      if (prev.left + prev.width + 0.9 >= range.left) {
        prev.width = Math.max(prev.width, range.left + range.width - prev.left);
      } else {
        result[resultLen++] = prev;
        prev = range;
      }
    }
    result[resultLen++] = prev;
    return result;
  }
  static _createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, clientRectScale) {
    if (!clientRects || clientRects.length === 0) {
      return null;
    }
    const result = [];
    for (let i = 0, len = clientRects.length; i < len; i++) {
      const clientRect = clientRects[i];
      result[i] = new FloatHorizontalRange(Math.max(0, (clientRect.left - clientRectDeltaLeft) / clientRectScale), clientRect.width / clientRectScale);
    }
    return this._mergeAdjacentRanges(result);
  }
  static readHorizontalRanges(domNode, startChildIndex, startOffset, endChildIndex, endOffset, clientRectDeltaLeft, clientRectScale, endNode) {
    const min = 0;
    const max = domNode.children.length - 1;
    if (min > max) {
      return null;
    }
    startChildIndex = Math.min(max, Math.max(min, startChildIndex));
    endChildIndex = Math.min(max, Math.max(min, endChildIndex));
    if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0 && !domNode.children[startChildIndex].firstChild) {
      const clientRects2 = domNode.children[startChildIndex].getClientRects();
      return this._createHorizontalRangesFromClientRects(clientRects2, clientRectDeltaLeft, clientRectScale);
    }
    if (startChildIndex !== endChildIndex) {
      if (endChildIndex > 0 && endOffset === 0) {
        endChildIndex--;
        endOffset = 1073741824;
      }
    }
    let startElement = domNode.children[startChildIndex].firstChild;
    let endElement = domNode.children[endChildIndex].firstChild;
    if (!startElement || !endElement) {
      if (!startElement && startOffset === 0 && startChildIndex > 0) {
        startElement = domNode.children[startChildIndex - 1].firstChild;
        startOffset = 1073741824;
      }
      if (!endElement && endOffset === 0 && endChildIndex > 0) {
        endElement = domNode.children[endChildIndex - 1].firstChild;
        endOffset = 1073741824;
      }
    }
    if (!startElement || !endElement) {
      return null;
    }
    startOffset = Math.min(startElement.textContent.length, Math.max(0, startOffset));
    endOffset = Math.min(endElement.textContent.length, Math.max(0, endOffset));
    const clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode);
    return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, clientRectScale);
  }
}
export {
  RangeUtil
};
