"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const position = require("../core/position.js");
const range = require("../core/range.js");
const viewModel = require("../viewModel.js");
const editorOptions = require("../config/editorOptions.js");
class ViewModelDecorations {
  constructor(editorId, model, configuration, linesCollection, coordinatesConverter) {
    this.editorId = editorId;
    this.model = model;
    this.configuration = configuration;
    this._linesCollection = linesCollection;
    this._coordinatesConverter = coordinatesConverter;
    this._decorationsCache = /* @__PURE__ */ Object.create(null);
    this._cachedModelDecorationsResolver = null;
    this._cachedModelDecorationsResolverViewRange = null;
  }
  _clearCachedModelDecorationsResolver() {
    this._cachedModelDecorationsResolver = null;
    this._cachedModelDecorationsResolverViewRange = null;
  }
  dispose() {
    this._decorationsCache = /* @__PURE__ */ Object.create(null);
    this._clearCachedModelDecorationsResolver();
  }
  reset() {
    this._decorationsCache = /* @__PURE__ */ Object.create(null);
    this._clearCachedModelDecorationsResolver();
  }
  onModelDecorationsChanged() {
    this._decorationsCache = /* @__PURE__ */ Object.create(null);
    this._clearCachedModelDecorationsResolver();
  }
  onLineMappingChanged() {
    this._decorationsCache = /* @__PURE__ */ Object.create(null);
    this._clearCachedModelDecorationsResolver();
  }
  _getOrCreateViewModelDecoration(modelDecoration) {
    const id = modelDecoration.id;
    let r = this._decorationsCache[id];
    if (!r) {
      const modelRange = modelDecoration.range;
      const options = modelDecoration.options;
      let viewRange;
      if (options.isWholeLine) {
        const start = this._coordinatesConverter.convertModelPositionToViewPosition(
          new position.Position(modelRange.startLineNumber, 1),
          0
          /* Left */
        );
        const end = this._coordinatesConverter.convertModelPositionToViewPosition(
          new position.Position(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber)),
          1
          /* Right */
        );
        viewRange = new range.Range(start.lineNumber, start.column, end.lineNumber, end.column);
      } else {
        viewRange = this._coordinatesConverter.convertModelRangeToViewRange(
          modelRange,
          1
          /* Right */
        );
      }
      r = new viewModel.ViewModelDecoration(viewRange, options);
      this._decorationsCache[id] = r;
    }
    return r;
  }
  getDecorationsViewportData(viewRange) {
    let cacheIsValid = this._cachedModelDecorationsResolver !== null;
    cacheIsValid = cacheIsValid && viewRange.equalsRange(this._cachedModelDecorationsResolverViewRange);
    if (!cacheIsValid) {
      this._cachedModelDecorationsResolver = this._getDecorationsViewportData(viewRange);
      this._cachedModelDecorationsResolverViewRange = viewRange;
    }
    return this._cachedModelDecorationsResolver;
  }
  _getDecorationsViewportData(viewportRange) {
    const modelDecorations = this._linesCollection.getDecorationsInRange(viewportRange, this.editorId, editorOptions.filterValidationDecorations(this.configuration.options));
    const startLineNumber = viewportRange.startLineNumber;
    const endLineNumber = viewportRange.endLineNumber;
    const decorationsInViewport = [];
    let decorationsInViewportLen = 0;
    const inlineDecorations = [];
    for (let j = startLineNumber; j <= endLineNumber; j++) {
      inlineDecorations[j - startLineNumber] = [];
    }
    for (let i = 0, len = modelDecorations.length; i < len; i++) {
      const modelDecoration = modelDecorations[i];
      const decorationOptions = modelDecoration.options;
      if (!isModelDecorationVisible(this.model, modelDecoration)) {
        continue;
      }
      const viewModelDecoration = this._getOrCreateViewModelDecoration(modelDecoration);
      const viewRange = viewModelDecoration.range;
      decorationsInViewport[decorationsInViewportLen++] = viewModelDecoration;
      if (decorationOptions.inlineClassName) {
        const inlineDecoration = new viewModel.InlineDecoration(
          viewRange,
          decorationOptions.inlineClassName,
          decorationOptions.inlineClassNameAffectsLetterSpacing ? 3 : 0
          /* Regular */
        );
        const intersectedStartLineNumber = Math.max(startLineNumber, viewRange.startLineNumber);
        const intersectedEndLineNumber = Math.min(endLineNumber, viewRange.endLineNumber);
        for (let j = intersectedStartLineNumber; j <= intersectedEndLineNumber; j++) {
          inlineDecorations[j - startLineNumber].push(inlineDecoration);
        }
      }
      if (decorationOptions.beforeContentClassName) {
        if (startLineNumber <= viewRange.startLineNumber && viewRange.startLineNumber <= endLineNumber) {
          const inlineDecoration = new viewModel.InlineDecoration(
            new range.Range(viewRange.startLineNumber, viewRange.startColumn, viewRange.startLineNumber, viewRange.startColumn),
            decorationOptions.beforeContentClassName,
            1
            /* Before */
          );
          inlineDecorations[viewRange.startLineNumber - startLineNumber].push(inlineDecoration);
        }
      }
      if (decorationOptions.afterContentClassName) {
        if (startLineNumber <= viewRange.endLineNumber && viewRange.endLineNumber <= endLineNumber) {
          const inlineDecoration = new viewModel.InlineDecoration(
            new range.Range(viewRange.endLineNumber, viewRange.endColumn, viewRange.endLineNumber, viewRange.endColumn),
            decorationOptions.afterContentClassName,
            2
            /* After */
          );
          inlineDecorations[viewRange.endLineNumber - startLineNumber].push(inlineDecoration);
        }
      }
    }
    return {
      decorations: decorationsInViewport,
      inlineDecorations
    };
  }
}
function isModelDecorationVisible(model, decoration) {
  if (decoration.options.hideInCommentTokens && isModelDecorationInComment(model, decoration)) {
    return false;
  }
  if (decoration.options.hideInStringTokens && isModelDecorationInString(model, decoration)) {
    return false;
  }
  return true;
}
function isModelDecorationInComment(model, decoration) {
  return testTokensInRange(
    model,
    decoration.range,
    (tokenType) => tokenType === 1
    /* Comment */
  );
}
function isModelDecorationInString(model, decoration) {
  return testTokensInRange(
    model,
    decoration.range,
    (tokenType) => tokenType === 2
    /* String */
  );
}
function testTokensInRange(model, range2, callback) {
  for (let lineNumber = range2.startLineNumber; lineNumber <= range2.endLineNumber; lineNumber++) {
    const lineTokens = model.getLineTokens(lineNumber);
    const isFirstLine = lineNumber === range2.startLineNumber;
    const isEndLine = lineNumber === range2.endLineNumber;
    let tokenIdx = isFirstLine ? lineTokens.findTokenIndexAtOffset(range2.startColumn - 1) : 0;
    while (tokenIdx < lineTokens.getCount()) {
      if (isEndLine) {
        const startOffset = lineTokens.getStartOffset(tokenIdx);
        if (startOffset > range2.endColumn - 1) {
          break;
        }
      }
      const callbackResult = callback(lineTokens.getStandardTokenType(tokenIdx));
      if (!callbackResult) {
        return false;
      }
      tokenIdx++;
    }
  }
  return true;
}
exports.ViewModelDecorations = ViewModelDecorations;
exports.isModelDecorationInComment = isModelDecorationInComment;
exports.isModelDecorationInString = isModelDecorationInString;
exports.isModelDecorationVisible = isModelDecorationVisible;
