"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const cursorCommon = require("../cursorCommon.js");
const position = require("../core/position.js");
const range = require("../core/range.js");
const selection = require("../core/selection.js");
class Cursor {
  constructor(context) {
    this._selTrackedRange = null;
    this._trackSelection = true;
    this._setState(context, new cursorCommon.SingleCursorState(new range.Range(1, 1, 1, 1), 0, new position.Position(1, 1), 0), new cursorCommon.SingleCursorState(new range.Range(1, 1, 1, 1), 0, new position.Position(1, 1), 0));
  }
  dispose(context) {
    this._removeTrackedRange(context);
  }
  startTrackingSelection(context) {
    this._trackSelection = true;
    this._updateTrackedRange(context);
  }
  stopTrackingSelection(context) {
    this._trackSelection = false;
    this._removeTrackedRange(context);
  }
  _updateTrackedRange(context) {
    if (!this._trackSelection) {
      return;
    }
    this._selTrackedRange = context.model._setTrackedRange(
      this._selTrackedRange,
      this.modelState.selection,
      0
      /* AlwaysGrowsWhenTypingAtEdges */
    );
  }
  _removeTrackedRange(context) {
    this._selTrackedRange = context.model._setTrackedRange(
      this._selTrackedRange,
      null,
      0
      /* AlwaysGrowsWhenTypingAtEdges */
    );
  }
  asCursorState() {
    return new cursorCommon.CursorState(this.modelState, this.viewState);
  }
  readSelectionFromMarkers(context) {
    const range2 = context.model._getTrackedRange(this._selTrackedRange);
    return selection.Selection.fromRange(range2, this.modelState.selection.getDirection());
  }
  ensureValidState(context) {
    this._setState(context, this.modelState, this.viewState);
  }
  setState(context, modelState, viewState) {
    this._setState(context, modelState, viewState);
  }
  static _validatePositionWithCache(viewModel, position2, cacheInput, cacheOutput) {
    if (position2.equals(cacheInput)) {
      return cacheOutput;
    }
    return viewModel.normalizePosition(
      position2,
      2
      /* None */
    );
  }
  static _validateViewState(viewModel, viewState) {
    const position2 = viewState.position;
    const sStartPosition = viewState.selectionStart.getStartPosition();
    const sEndPosition = viewState.selectionStart.getEndPosition();
    const validPosition = viewModel.normalizePosition(
      position2,
      2
      /* None */
    );
    const validSStartPosition = this._validatePositionWithCache(viewModel, sStartPosition, position2, validPosition);
    const validSEndPosition = this._validatePositionWithCache(viewModel, sEndPosition, sStartPosition, validSStartPosition);
    if (position2.equals(validPosition) && sStartPosition.equals(validSStartPosition) && sEndPosition.equals(validSEndPosition)) {
      return viewState;
    }
    return new cursorCommon.SingleCursorState(range.Range.fromPositions(validSStartPosition, validSEndPosition), viewState.selectionStartLeftoverVisibleColumns + sStartPosition.column - validSStartPosition.column, validPosition, viewState.leftoverVisibleColumns + position2.column - validPosition.column);
  }
  _setState(context, modelState, viewState) {
    if (viewState) {
      viewState = Cursor._validateViewState(context.viewModel, viewState);
    }
    if (!modelState) {
      if (!viewState) {
        return;
      }
      const selectionStart = context.model.validateRange(context.coordinatesConverter.convertViewRangeToModelRange(viewState.selectionStart));
      const position2 = context.model.validatePosition(context.coordinatesConverter.convertViewPositionToModelPosition(viewState.position));
      modelState = new cursorCommon.SingleCursorState(selectionStart, viewState.selectionStartLeftoverVisibleColumns, position2, viewState.leftoverVisibleColumns);
    } else {
      const selectionStart = context.model.validateRange(modelState.selectionStart);
      const selectionStartLeftoverVisibleColumns = modelState.selectionStart.equalsRange(selectionStart) ? modelState.selectionStartLeftoverVisibleColumns : 0;
      const position2 = context.model.validatePosition(modelState.position);
      const leftoverVisibleColumns = modelState.position.equals(position2) ? modelState.leftoverVisibleColumns : 0;
      modelState = new cursorCommon.SingleCursorState(selectionStart, selectionStartLeftoverVisibleColumns, position2, leftoverVisibleColumns);
    }
    if (!viewState) {
      const viewSelectionStart1 = context.coordinatesConverter.convertModelPositionToViewPosition(new position.Position(modelState.selectionStart.startLineNumber, modelState.selectionStart.startColumn));
      const viewSelectionStart2 = context.coordinatesConverter.convertModelPositionToViewPosition(new position.Position(modelState.selectionStart.endLineNumber, modelState.selectionStart.endColumn));
      const viewSelectionStart = new range.Range(viewSelectionStart1.lineNumber, viewSelectionStart1.column, viewSelectionStart2.lineNumber, viewSelectionStart2.column);
      const viewPosition = context.coordinatesConverter.convertModelPositionToViewPosition(modelState.position);
      viewState = new cursorCommon.SingleCursorState(viewSelectionStart, modelState.selectionStartLeftoverVisibleColumns, viewPosition, modelState.leftoverVisibleColumns);
    } else {
      const viewSelectionStart = context.coordinatesConverter.validateViewRange(viewState.selectionStart, modelState.selectionStart);
      const viewPosition = context.coordinatesConverter.validateViewPosition(viewState.position, modelState.position);
      viewState = new cursorCommon.SingleCursorState(viewSelectionStart, modelState.selectionStartLeftoverVisibleColumns, viewPosition, modelState.leftoverVisibleColumns);
    }
    this.modelState = modelState;
    this.viewState = viewState;
    this._updateTrackedRange(context);
  }
}
exports.Cursor = Cursor;
