"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const lifecycle = require("../../../../base/common/lifecycle.js");
const editorExtensions = require("../../../browser/editorExtensions.js");
const editorContextKeys = require("../../../common/editorContextKeys.js");
const nls = require("../../../../nls.js");
class CursorState {
  constructor(selections) {
    this.selections = selections;
  }
  equals(other) {
    const thisLen = this.selections.length;
    const otherLen = other.selections.length;
    if (thisLen !== otherLen) {
      return false;
    }
    for (let i = 0; i < thisLen; i++) {
      if (!this.selections[i].equalsSelection(other.selections[i])) {
        return false;
      }
    }
    return true;
  }
}
class StackElement {
  constructor(cursorState, scrollTop, scrollLeft) {
    this.cursorState = cursorState;
    this.scrollTop = scrollTop;
    this.scrollLeft = scrollLeft;
  }
}
class CursorUndoRedoController extends lifecycle.Disposable {
  constructor(editor) {
    super();
    this._editor = editor;
    this._isCursorUndoRedo = false;
    this._undoStack = [];
    this._redoStack = [];
    this._register(editor.onDidChangeModel((e) => {
      this._undoStack = [];
      this._redoStack = [];
    }));
    this._register(editor.onDidChangeModelContent((e) => {
      this._undoStack = [];
      this._redoStack = [];
    }));
    this._register(editor.onDidChangeCursorSelection((e) => {
      if (this._isCursorUndoRedo) {
        return;
      }
      if (!e.oldSelections) {
        return;
      }
      if (e.oldModelVersionId !== e.modelVersionId) {
        return;
      }
      const prevState = new CursorState(e.oldSelections);
      const isEqualToLastUndoStack = this._undoStack.length > 0 && this._undoStack[this._undoStack.length - 1].cursorState.equals(prevState);
      if (!isEqualToLastUndoStack) {
        this._undoStack.push(new StackElement(prevState, editor.getScrollTop(), editor.getScrollLeft()));
        this._redoStack = [];
        if (this._undoStack.length > 50) {
          this._undoStack.shift();
        }
      }
    }));
  }
  static get(editor) {
    return editor.getContribution(CursorUndoRedoController.ID);
  }
  cursorUndo() {
    if (!this._editor.hasModel() || this._undoStack.length === 0) {
      return;
    }
    this._redoStack.push(new StackElement(new CursorState(this._editor.getSelections()), this._editor.getScrollTop(), this._editor.getScrollLeft()));
    this._applyState(this._undoStack.pop());
  }
  cursorRedo() {
    if (!this._editor.hasModel() || this._redoStack.length === 0) {
      return;
    }
    this._undoStack.push(new StackElement(new CursorState(this._editor.getSelections()), this._editor.getScrollTop(), this._editor.getScrollLeft()));
    this._applyState(this._redoStack.pop());
  }
  _applyState(stackElement) {
    this._isCursorUndoRedo = true;
    this._editor.setSelections(stackElement.cursorState.selections);
    this._editor.setScrollPosition({
      scrollTop: stackElement.scrollTop,
      scrollLeft: stackElement.scrollLeft
    });
    this._isCursorUndoRedo = false;
  }
}
CursorUndoRedoController.ID = "editor.contrib.cursorUndoRedoController";
class CursorUndo extends editorExtensions.EditorAction {
  constructor() {
    super({
      id: "cursorUndo",
      label: nls.localize("cursor.undo", "Cursor Undo"),
      alias: "Cursor Undo",
      precondition: void 0,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.textInputFocus,
        primary: 2048 | 51,
        weight: 100
        /* EditorContrib */
      }
    });
  }
  run(accessor, editor, args) {
    var _a;
    (_a = CursorUndoRedoController.get(editor)) === null || _a === void 0 ? void 0 : _a.cursorUndo();
  }
}
class CursorRedo extends editorExtensions.EditorAction {
  constructor() {
    super({
      id: "cursorRedo",
      label: nls.localize("cursor.redo", "Cursor Redo"),
      alias: "Cursor Redo",
      precondition: void 0
    });
  }
  run(accessor, editor, args) {
    var _a;
    (_a = CursorUndoRedoController.get(editor)) === null || _a === void 0 ? void 0 : _a.cursorRedo();
  }
}
editorExtensions.registerEditorContribution(CursorUndoRedoController.ID, CursorUndoRedoController);
editorExtensions.registerEditorAction(CursorUndo);
editorExtensions.registerEditorAction(CursorRedo);
exports.CursorRedo = CursorRedo;
exports.CursorUndo = CursorUndo;
exports.CursorUndoRedoController = CursorUndoRedoController;
