import { findFirstInSorted } from "../../../../base/common/arrays.mjs";
import { Emitter } from "../../../../base/common/event.mjs";
import { Range } from "../../../common/core/range.mjs";
import { countEOL } from "../../../common/core/eolCounter.mjs";
class HiddenRangeModel {
  constructor(model) {
    this._updateEventEmitter = new Emitter();
    this._hasLineChanges = false;
    this._foldingModel = model;
    this._foldingModelListener = model.onDidChange((_) => this.updateHiddenRanges());
    this._hiddenRanges = [];
    if (model.regions.length) {
      this.updateHiddenRanges();
    }
  }
  get onDidChange() {
    return this._updateEventEmitter.event;
  }
  get hiddenRanges() {
    return this._hiddenRanges;
  }
  notifyChangeModelContent(e) {
    if (this._hiddenRanges.length && !this._hasLineChanges) {
      this._hasLineChanges = e.changes.some((change) => {
        return change.range.endLineNumber !== change.range.startLineNumber || countEOL(change.text)[0] !== 0;
      });
    }
  }
  updateHiddenRanges() {
    let updateHiddenAreas = false;
    let newHiddenAreas = [];
    let i = 0;
    let k = 0;
    let lastCollapsedStart = Number.MAX_VALUE;
    let lastCollapsedEnd = -1;
    let ranges = this._foldingModel.regions;
    for (; i < ranges.length; i++) {
      if (!ranges.isCollapsed(i)) {
        continue;
      }
      let startLineNumber = ranges.getStartLineNumber(i) + 1;
      let endLineNumber = ranges.getEndLineNumber(i);
      if (lastCollapsedStart <= startLineNumber && endLineNumber <= lastCollapsedEnd) {
        continue;
      }
      if (!updateHiddenAreas && k < this._hiddenRanges.length && this._hiddenRanges[k].startLineNumber === startLineNumber && this._hiddenRanges[k].endLineNumber === endLineNumber) {
        newHiddenAreas.push(this._hiddenRanges[k]);
        k++;
      } else {
        updateHiddenAreas = true;
        newHiddenAreas.push(new Range(startLineNumber, 1, endLineNumber, 1));
      }
      lastCollapsedStart = startLineNumber;
      lastCollapsedEnd = endLineNumber;
    }
    if (this._hasLineChanges || updateHiddenAreas || k < this._hiddenRanges.length) {
      this.applyHiddenRanges(newHiddenAreas);
    }
  }
  applyMemento(state) {
    if (!Array.isArray(state) || state.length === 0) {
      return false;
    }
    let hiddenRanges = [];
    for (let r of state) {
      if (!r.startLineNumber || !r.endLineNumber) {
        return false;
      }
      hiddenRanges.push(new Range(r.startLineNumber + 1, 1, r.endLineNumber, 1));
    }
    this.applyHiddenRanges(hiddenRanges);
    return true;
  }
  /**
   * Collapse state memento, for persistence only, only used if folding model is not yet initialized
   */
  getMemento() {
    return this._hiddenRanges.map((r) => ({ startLineNumber: r.startLineNumber - 1, endLineNumber: r.endLineNumber }));
  }
  applyHiddenRanges(newHiddenAreas) {
    this._hiddenRanges = newHiddenAreas;
    this._hasLineChanges = false;
    this._updateEventEmitter.fire(newHiddenAreas);
  }
  hasRanges() {
    return this._hiddenRanges.length > 0;
  }
  isHidden(line) {
    return findRange(this._hiddenRanges, line) !== null;
  }
  adjustSelections(selections) {
    let hasChanges = false;
    let editorModel = this._foldingModel.textModel;
    let lastRange = null;
    let adjustLine = (line) => {
      if (!lastRange || !isInside(line, lastRange)) {
        lastRange = findRange(this._hiddenRanges, line);
      }
      if (lastRange) {
        return lastRange.startLineNumber - 1;
      }
      return null;
    };
    for (let i = 0, len = selections.length; i < len; i++) {
      let selection = selections[i];
      let adjustedStartLine = adjustLine(selection.startLineNumber);
      if (adjustedStartLine) {
        selection = selection.setStartPosition(adjustedStartLine, editorModel.getLineMaxColumn(adjustedStartLine));
        hasChanges = true;
      }
      let adjustedEndLine = adjustLine(selection.endLineNumber);
      if (adjustedEndLine) {
        selection = selection.setEndPosition(adjustedEndLine, editorModel.getLineMaxColumn(adjustedEndLine));
        hasChanges = true;
      }
      selections[i] = selection;
    }
    return hasChanges;
  }
  dispose() {
    if (this.hiddenRanges.length > 0) {
      this._hiddenRanges = [];
      this._updateEventEmitter.fire(this._hiddenRanges);
    }
    if (this._foldingModelListener) {
      this._foldingModelListener.dispose();
      this._foldingModelListener = null;
    }
  }
}
function isInside(line, range) {
  return line >= range.startLineNumber && line <= range.endLineNumber;
}
function findRange(ranges, line) {
  let i = findFirstInSorted(ranges, (r) => line < r.startLineNumber) - 1;
  if (i >= 0 && ranges[i].endLineNumber >= line) {
    return ranges[i];
  }
  return null;
}
export {
  HiddenRangeModel
};
