"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const assert = require("../../../base/common/assert.js");
const event = require("../../../base/common/event.js");
const lifecycle = require("../../../base/common/lifecycle.js");
const objects = require("../../../base/common/objects.js");
const range = require("../../common/core/range.js");
const defaultOptions = {
  followsCaret: true,
  ignoreCharChanges: true,
  alwaysRevealFirst: true
};
class DiffNavigator extends lifecycle.Disposable {
  constructor(editor, options = {}) {
    super();
    this._onDidUpdate = this._register(new event.Emitter());
    this._editor = editor;
    this._options = objects.mixin(options, defaultOptions, false);
    this.disposed = false;
    this.nextIdx = -1;
    this.ranges = [];
    this.ignoreSelectionChange = false;
    this.revealFirst = Boolean(this._options.alwaysRevealFirst);
    this._register(this._editor.onDidDispose(() => this.dispose()));
    this._register(this._editor.onDidUpdateDiff(() => this._onDiffUpdated()));
    if (this._options.followsCaret) {
      this._register(this._editor.getModifiedEditor().onDidChangeCursorPosition((e) => {
        if (this.ignoreSelectionChange) {
          return;
        }
        this.nextIdx = -1;
      }));
    }
    if (this._options.alwaysRevealFirst) {
      this._register(this._editor.getModifiedEditor().onDidChangeModel((e) => {
        this.revealFirst = true;
      }));
    }
    this._init();
  }
  _init() {
    const changes = this._editor.getLineChanges();
    if (!changes) {
      return;
    }
  }
  _onDiffUpdated() {
    this._init();
    this._compute(this._editor.getLineChanges());
    if (this.revealFirst) {
      if (this._editor.getLineChanges() !== null) {
        this.revealFirst = false;
        this.nextIdx = -1;
        this.next(
          1
          /* Immediate */
        );
      }
    }
  }
  _compute(lineChanges) {
    this.ranges = [];
    if (lineChanges) {
      lineChanges.forEach((lineChange) => {
        if (!this._options.ignoreCharChanges && lineChange.charChanges) {
          lineChange.charChanges.forEach((charChange) => {
            this.ranges.push({
              rhs: true,
              range: new range.Range(charChange.modifiedStartLineNumber, charChange.modifiedStartColumn, charChange.modifiedEndLineNumber, charChange.modifiedEndColumn)
            });
          });
        } else {
          if (lineChange.modifiedEndLineNumber === 0) {
            this.ranges.push({
              rhs: true,
              range: new range.Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedStartLineNumber + 1, 1)
            });
          } else {
            this.ranges.push({
              rhs: true,
              range: new range.Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber + 1, 1)
            });
          }
        }
      });
    }
    this.ranges.sort((left, right) => range.Range.compareRangesUsingStarts(left.range, right.range));
    this._onDidUpdate.fire(this);
  }
  _initIdx(fwd) {
    let found = false;
    const position = this._editor.getPosition();
    if (!position) {
      this.nextIdx = 0;
      return;
    }
    for (let i = 0, len = this.ranges.length; i < len && !found; i++) {
      const range2 = this.ranges[i].range;
      if (position.isBeforeOrEqual(range2.getStartPosition())) {
        this.nextIdx = i + (fwd ? 0 : -1);
        found = true;
      }
    }
    if (!found) {
      this.nextIdx = fwd ? 0 : this.ranges.length - 1;
    }
    if (this.nextIdx < 0) {
      this.nextIdx = this.ranges.length - 1;
    }
  }
  _move(fwd, scrollType) {
    assert.ok(!this.disposed, "Illegal State - diff navigator has been disposed");
    if (!this.canNavigate()) {
      return;
    }
    if (this.nextIdx === -1) {
      this._initIdx(fwd);
    } else if (fwd) {
      this.nextIdx += 1;
      if (this.nextIdx >= this.ranges.length) {
        this.nextIdx = 0;
      }
    } else {
      this.nextIdx -= 1;
      if (this.nextIdx < 0) {
        this.nextIdx = this.ranges.length - 1;
      }
    }
    const info = this.ranges[this.nextIdx];
    this.ignoreSelectionChange = true;
    try {
      const pos = info.range.getStartPosition();
      this._editor.setPosition(pos);
      this._editor.revealRangeInCenter(info.range, scrollType);
    } finally {
      this.ignoreSelectionChange = false;
    }
  }
  canNavigate() {
    return this.ranges && this.ranges.length > 0;
  }
  next(scrollType = 0) {
    this._move(true, scrollType);
  }
  previous(scrollType = 0) {
    this._move(false, scrollType);
  }
  dispose() {
    super.dispose();
    this.ranges = [];
    this.disposed = true;
  }
}
exports.DiffNavigator = DiffNavigator;
