import { SingleCursorState, CursorState } from "../cursorCommon.mjs";
import { Position } from "../core/position.mjs";
import { Range } from "../core/range.mjs";
import { Selection } from "../core/selection.mjs";
class Cursor {
  constructor(context) {
    this._selTrackedRange = null;
    this._trackSelection = true;
    this._setState(context, new SingleCursorState(new Range(1, 1, 1, 1), 0, new Position(1, 1), 0), new SingleCursorState(new Range(1, 1, 1, 1), 0, new 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 CursorState(this.modelState, this.viewState);
  }
  readSelectionFromMarkers(context) {
    const range = context.model._getTrackedRange(this._selTrackedRange);
    return Selection.fromRange(range, 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, position, cacheInput, cacheOutput) {
    if (position.equals(cacheInput)) {
      return cacheOutput;
    }
    return viewModel.normalizePosition(
      position,
      2
      /* None */
    );
  }
  static _validateViewState(viewModel, viewState) {
    const position = viewState.position;
    const sStartPosition = viewState.selectionStart.getStartPosition();
    const sEndPosition = viewState.selectionStart.getEndPosition();
    const validPosition = viewModel.normalizePosition(
      position,
      2
      /* None */
    );
    const validSStartPosition = this._validatePositionWithCache(viewModel, sStartPosition, position, validPosition);
    const validSEndPosition = this._validatePositionWithCache(viewModel, sEndPosition, sStartPosition, validSStartPosition);
    if (position.equals(validPosition) && sStartPosition.equals(validSStartPosition) && sEndPosition.equals(validSEndPosition)) {
      return viewState;
    }
    return new SingleCursorState(Range.fromPositions(validSStartPosition, validSEndPosition), viewState.selectionStartLeftoverVisibleColumns + sStartPosition.column - validSStartPosition.column, validPosition, viewState.leftoverVisibleColumns + position.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 position = context.model.validatePosition(context.coordinatesConverter.convertViewPositionToModelPosition(viewState.position));
      modelState = new SingleCursorState(selectionStart, viewState.selectionStartLeftoverVisibleColumns, position, viewState.leftoverVisibleColumns);
    } else {
      const selectionStart = context.model.validateRange(modelState.selectionStart);
      const selectionStartLeftoverVisibleColumns = modelState.selectionStart.equalsRange(selectionStart) ? modelState.selectionStartLeftoverVisibleColumns : 0;
      const position = context.model.validatePosition(modelState.position);
      const leftoverVisibleColumns = modelState.position.equals(position) ? modelState.leftoverVisibleColumns : 0;
      modelState = new SingleCursorState(selectionStart, selectionStartLeftoverVisibleColumns, position, leftoverVisibleColumns);
    }
    if (!viewState) {
      const viewSelectionStart1 = context.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelState.selectionStart.startLineNumber, modelState.selectionStart.startColumn));
      const viewSelectionStart2 = context.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelState.selectionStart.endLineNumber, modelState.selectionStart.endColumn));
      const viewSelectionStart = new Range(viewSelectionStart1.lineNumber, viewSelectionStart1.column, viewSelectionStart2.lineNumber, viewSelectionStart2.column);
      const viewPosition = context.coordinatesConverter.convertModelPositionToViewPosition(modelState.position);
      viewState = new 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 SingleCursorState(viewSelectionStart, modelState.selectionStartLeftoverVisibleColumns, viewPosition, modelState.leftoverVisibleColumns);
    }
    this.modelState = modelState;
    this.viewState = viewState;
    this._updateTrackedRange(context);
  }
}
export {
  Cursor
};
