"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const length = require("./length.js");
class TextEditInfo {
  constructor(startOffset, endOffset, newLength) {
    this.startOffset = startOffset;
    this.endOffset = endOffset;
    this.newLength = newLength;
  }
}
class BeforeEditPositionMapper {
  /**
   * @param edits Must be sorted by offset in ascending order.
  */
  constructor(edits, documentLength) {
    this.documentLength = documentLength;
    this.nextEditIdx = 0;
    this.deltaOldToNewLineCount = 0;
    this.deltaOldToNewColumnCount = 0;
    this.deltaLineIdxInOld = -1;
    this.edits = edits.map((edit) => TextEditInfoCache.from(edit));
  }
  /**
   * @param offset Must be equal to or greater than the last offset this method has been called with.
  */
  getOffsetBeforeChange(offset) {
    this.adjustNextEdit(offset);
    return this.translateCurToOld(offset);
  }
  /**
   * @param offset Must be equal to or greater than the last offset this method has been called with.
  */
  getDistanceToNextChange(offset) {
    this.adjustNextEdit(offset);
    const nextEdit = this.edits[this.nextEditIdx];
    const nextChangeOffset = nextEdit ? this.translateOldToCur(nextEdit.offsetObj) : this.documentLength;
    return length.lengthDiffNonNegative(offset, nextChangeOffset);
  }
  translateOldToCur(oldOffsetObj) {
    if (oldOffsetObj.lineCount === this.deltaLineIdxInOld) {
      return length.toLength(oldOffsetObj.lineCount + this.deltaOldToNewLineCount, oldOffsetObj.columnCount + this.deltaOldToNewColumnCount);
    } else {
      return length.toLength(oldOffsetObj.lineCount + this.deltaOldToNewLineCount, oldOffsetObj.columnCount);
    }
  }
  translateCurToOld(newOffset) {
    const offsetObj = length.lengthToObj(newOffset);
    if (offsetObj.lineCount - this.deltaOldToNewLineCount === this.deltaLineIdxInOld) {
      return length.toLength(offsetObj.lineCount - this.deltaOldToNewLineCount, offsetObj.columnCount - this.deltaOldToNewColumnCount);
    } else {
      return length.toLength(offsetObj.lineCount - this.deltaOldToNewLineCount, offsetObj.columnCount);
    }
  }
  adjustNextEdit(offset) {
    while (this.nextEditIdx < this.edits.length) {
      const nextEdit = this.edits[this.nextEditIdx];
      const nextEditEndOffsetInCur = this.translateOldToCur(nextEdit.endOffsetAfterObj);
      if (length.lengthLessThanEqual(nextEditEndOffsetInCur, offset)) {
        this.nextEditIdx++;
        const nextEditEndOffsetInCurObj = length.lengthToObj(nextEditEndOffsetInCur);
        const nextEditEndOffsetBeforeInCurObj = length.lengthToObj(this.translateOldToCur(nextEdit.endOffsetBeforeObj));
        const lineDelta = nextEditEndOffsetInCurObj.lineCount - nextEditEndOffsetBeforeInCurObj.lineCount;
        this.deltaOldToNewLineCount += lineDelta;
        const previousColumnDelta = this.deltaLineIdxInOld === nextEdit.endOffsetBeforeObj.lineCount ? this.deltaOldToNewColumnCount : 0;
        const columnDelta = nextEditEndOffsetInCurObj.columnCount - nextEditEndOffsetBeforeInCurObj.columnCount;
        this.deltaOldToNewColumnCount = previousColumnDelta + columnDelta;
        this.deltaLineIdxInOld = nextEdit.endOffsetBeforeObj.lineCount;
      } else {
        break;
      }
    }
  }
}
class TextEditInfoCache {
  constructor(startOffset, endOffset, textLength) {
    this.endOffsetBeforeObj = length.lengthToObj(endOffset);
    this.endOffsetAfterObj = length.lengthToObj(length.lengthAdd(startOffset, textLength));
    this.offsetObj = length.lengthToObj(startOffset);
  }
  static from(edit) {
    return new TextEditInfoCache(edit.startOffset, edit.endOffset, edit.newLength);
  }
}
exports.BeforeEditPositionMapper = BeforeEditPositionMapper;
exports.TextEditInfo = TextEditInfo;
