import { computeScreenAwareSize } from "../../../../base/browser/dom.mjs";
import { createFastDomNode } from "../../../../base/browser/fastDomNode.mjs";
import { getCharContainingOffset } from "../../../../base/common/strings.mjs";
import { applyFontInfo } from "../../config/domFontInfo.mjs";
import { TextEditorCursorStyle } from "../../../common/config/editorOptions.mjs";
import { Position } from "../../../common/core/position.mjs";
import { Range } from "../../../common/core/range.mjs";
import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from "../../../../base/browser/ui/mouseCursor/mouseCursor.mjs";
class ViewCursorRenderData {
  constructor(top, left, width, height, textContent, textContentClassName) {
    this.top = top;
    this.left = left;
    this.width = width;
    this.height = height;
    this.textContent = textContent;
    this.textContentClassName = textContentClassName;
  }
}
class ViewCursor {
  constructor(context) {
    this._context = context;
    const options = this._context.configuration.options;
    const fontInfo = options.get(
      44
      /* fontInfo */
    );
    this._cursorStyle = options.get(
      24
      /* cursorStyle */
    );
    this._lineHeight = options.get(
      59
      /* lineHeight */
    );
    this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;
    this._lineCursorWidth = Math.min(options.get(
      27
      /* cursorWidth */
    ), this._typicalHalfwidthCharacterWidth);
    this._isVisible = true;
    this._domNode = createFastDomNode(document.createElement("div"));
    this._domNode.setClassName(`cursor ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`);
    this._domNode.setHeight(this._lineHeight);
    this._domNode.setTop(0);
    this._domNode.setLeft(0);
    applyFontInfo(this._domNode, fontInfo);
    this._domNode.setDisplay("none");
    this._position = new Position(1, 1);
    this._lastRenderedContent = "";
    this._renderData = null;
  }
  getDomNode() {
    return this._domNode;
  }
  getPosition() {
    return this._position;
  }
  show() {
    if (!this._isVisible) {
      this._domNode.setVisibility("inherit");
      this._isVisible = true;
    }
  }
  hide() {
    if (this._isVisible) {
      this._domNode.setVisibility("hidden");
      this._isVisible = false;
    }
  }
  onConfigurationChanged(e) {
    const options = this._context.configuration.options;
    const fontInfo = options.get(
      44
      /* fontInfo */
    );
    this._cursorStyle = options.get(
      24
      /* cursorStyle */
    );
    this._lineHeight = options.get(
      59
      /* lineHeight */
    );
    this._typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;
    this._lineCursorWidth = Math.min(options.get(
      27
      /* cursorWidth */
    ), this._typicalHalfwidthCharacterWidth);
    applyFontInfo(this._domNode, fontInfo);
    return true;
  }
  onCursorPositionChanged(position) {
    this._position = position;
    return true;
  }
  /**
   * If `this._position` is inside a grapheme, returns the position where the grapheme starts.
   * Also returns the next grapheme.
   */
  _getGraphemeAwarePosition() {
    const { lineNumber, column } = this._position;
    const lineContent = this._context.viewModel.getLineContent(lineNumber);
    const [startOffset, endOffset] = getCharContainingOffset(lineContent, column - 1);
    return [new Position(lineNumber, startOffset + 1), lineContent.substring(startOffset, endOffset)];
  }
  _prepareRender(ctx) {
    let textContent = "";
    const [position, nextGrapheme] = this._getGraphemeAwarePosition();
    if (this._cursorStyle === TextEditorCursorStyle.Line || this._cursorStyle === TextEditorCursorStyle.LineThin) {
      const visibleRange = ctx.visibleRangeForPosition(position);
      if (!visibleRange || visibleRange.outsideRenderedLine) {
        return null;
      }
      let width2;
      if (this._cursorStyle === TextEditorCursorStyle.Line) {
        width2 = computeScreenAwareSize(this._lineCursorWidth > 0 ? this._lineCursorWidth : 2);
        if (width2 > 2) {
          textContent = nextGrapheme;
        }
      } else {
        width2 = computeScreenAwareSize(1);
      }
      let left = visibleRange.left;
      if (width2 >= 2 && left >= 1) {
        left -= 1;
      }
      const top2 = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;
      return new ViewCursorRenderData(top2, left, width2, this._lineHeight, textContent, "");
    }
    const visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(position.lineNumber, position.column, position.lineNumber, position.column + nextGrapheme.length), false);
    if (!visibleRangeForCharacter || visibleRangeForCharacter.length === 0) {
      return null;
    }
    const firstVisibleRangeForCharacter = visibleRangeForCharacter[0];
    if (firstVisibleRangeForCharacter.outsideRenderedLine || firstVisibleRangeForCharacter.ranges.length === 0) {
      return null;
    }
    const range = firstVisibleRangeForCharacter.ranges[0];
    const width = range.width < 1 ? this._typicalHalfwidthCharacterWidth : range.width;
    let textContentClassName = "";
    if (this._cursorStyle === TextEditorCursorStyle.Block) {
      const lineData = this._context.viewModel.getViewLineData(position.lineNumber);
      textContent = nextGrapheme;
      const tokenIndex = lineData.tokens.findTokenIndexAtOffset(position.column - 1);
      textContentClassName = lineData.tokens.getClassName(tokenIndex);
    }
    let top = ctx.getVerticalOffsetForLineNumber(position.lineNumber) - ctx.bigNumbersDelta;
    let height = this._lineHeight;
    if (this._cursorStyle === TextEditorCursorStyle.Underline || this._cursorStyle === TextEditorCursorStyle.UnderlineThin) {
      top += this._lineHeight - 2;
      height = 2;
    }
    return new ViewCursorRenderData(top, range.left, width, height, textContent, textContentClassName);
  }
  prepareRender(ctx) {
    this._renderData = this._prepareRender(ctx);
  }
  render(ctx) {
    if (!this._renderData) {
      this._domNode.setDisplay("none");
      return null;
    }
    if (this._lastRenderedContent !== this._renderData.textContent) {
      this._lastRenderedContent = this._renderData.textContent;
      this._domNode.domNode.textContent = this._lastRenderedContent;
    }
    this._domNode.setClassName(`cursor ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME} ${this._renderData.textContentClassName}`);
    this._domNode.setDisplay("block");
    this._domNode.setTop(this._renderData.top);
    this._domNode.setLeft(this._renderData.left);
    this._domNode.setWidth(this._renderData.width);
    this._domNode.setLineHeight(this._renderData.height);
    this._domNode.setHeight(this._renderData.height);
    return {
      domNode: this._domNode.domNode,
      position: this._position,
      contentLeft: this._renderData.left,
      height: this._renderData.height,
      width: 2
    };
  }
}
export {
  ViewCursor
};
