"use strict";
const async = require("../../../../base/common/async.js");
const lifecycle = require("../../../../base/common/lifecycle.js");
const editorExtensions = require("../../../browser/editorExtensions.js");
const getSemanticTokens = require("../../../common/services/getSemanticTokens.js");
const model = require("../../../common/services/model.js");
const modelService = require("../../../common/services/modelService.js");
const semanticTokensProviderStyling = require("../../../common/services/semanticTokensProviderStyling.js");
const configuration = require("../../../../platform/configuration/common/configuration.js");
const themeService = require("../../../../platform/theme/common/themeService.js");
const languageFeatureDebounce = require("../../../common/services/languageFeatureDebounce.js");
const stopwatch = require("../../../../base/common/stopwatch.js");
const languageFeatures = require("../../../common/services/languageFeatures.js");
var __decorate = globalThis && globalThis.__decorate || function(decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
    r = Reflect.decorate(decorators, target, key, desc);
  else
    for (var i = decorators.length - 1; i >= 0; i--)
      if (d = decorators[i])
        r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = globalThis && globalThis.__param || function(paramIndex, decorator) {
  return function(target, key) {
    decorator(target, key, paramIndex);
  };
};
let ViewportSemanticTokensContribution = class ViewportSemanticTokensContribution2 extends lifecycle.Disposable {
  constructor(editor, _modelService, _themeService, _configurationService, languageFeatureDebounceService, languageFeaturesService) {
    super();
    this._modelService = _modelService;
    this._themeService = _themeService;
    this._configurationService = _configurationService;
    this._editor = editor;
    this._provider = languageFeaturesService.documentRangeSemanticTokensProvider;
    this._debounceInformation = languageFeatureDebounceService.for(this._provider, "DocumentRangeSemanticTokens", { min: 100, max: 500 });
    this._tokenizeViewport = this._register(new async.RunOnceScheduler(() => this._tokenizeViewportNow(), 100));
    this._outstandingRequests = [];
    const scheduleTokenizeViewport = () => {
      if (this._editor.hasModel()) {
        this._tokenizeViewport.schedule(this._debounceInformation.get(this._editor.getModel()));
      }
    };
    this._register(this._editor.onDidScrollChange(() => {
      scheduleTokenizeViewport();
    }));
    this._register(this._editor.onDidChangeModel(() => {
      this._cancelAll();
      scheduleTokenizeViewport();
    }));
    this._register(this._editor.onDidChangeModelContent((e) => {
      this._cancelAll();
      scheduleTokenizeViewport();
    }));
    this._register(this._provider.onDidChange(() => {
      this._cancelAll();
      scheduleTokenizeViewport();
    }));
    this._register(this._configurationService.onDidChangeConfiguration((e) => {
      if (e.affectsConfiguration(modelService.SEMANTIC_HIGHLIGHTING_SETTING_ID)) {
        this._cancelAll();
        scheduleTokenizeViewport();
      }
    }));
    this._register(this._themeService.onDidColorThemeChange(() => {
      this._cancelAll();
      scheduleTokenizeViewport();
    }));
  }
  _cancelAll() {
    for (const request of this._outstandingRequests) {
      request.cancel();
    }
    this._outstandingRequests = [];
  }
  _removeOutstandingRequest(req) {
    for (let i = 0, len = this._outstandingRequests.length; i < len; i++) {
      if (this._outstandingRequests[i] === req) {
        this._outstandingRequests.splice(i, 1);
        return;
      }
    }
  }
  _tokenizeViewportNow() {
    if (!this._editor.hasModel()) {
      return;
    }
    const model2 = this._editor.getModel();
    if (model2.hasCompleteSemanticTokens()) {
      return;
    }
    if (!modelService.isSemanticColoringEnabled(model2, this._themeService, this._configurationService)) {
      if (model2.hasSomeSemanticTokens()) {
        model2.setSemanticTokens(null, false);
      }
      return;
    }
    if (!getSemanticTokens.hasDocumentRangeSemanticTokensProvider(this._provider, model2)) {
      if (model2.hasSomeSemanticTokens()) {
        model2.setSemanticTokens(null, false);
      }
      return;
    }
    const visibleRanges = this._editor.getVisibleRangesPlusViewportAboveBelow();
    this._outstandingRequests = this._outstandingRequests.concat(visibleRanges.map((range) => this._requestRange(model2, range)));
  }
  _requestRange(model2, range) {
    const requestVersionId = model2.getVersionId();
    const request = async.createCancelablePromise((token) => Promise.resolve(getSemanticTokens.getDocumentRangeSemanticTokens(this._provider, model2, range, token)));
    const sw = new stopwatch.StopWatch(false);
    request.then((r) => {
      this._debounceInformation.update(model2, sw.elapsed());
      if (!r || !r.tokens || model2.isDisposed() || model2.getVersionId() !== requestVersionId) {
        return;
      }
      const { provider, tokens: result } = r;
      const styling = this._modelService.getSemanticTokensProviderStyling(provider);
      model2.setPartialSemanticTokens(range, semanticTokensProviderStyling.toMultilineTokens2(result, styling, model2.getLanguageId()));
    }).then(() => this._removeOutstandingRequest(request), () => this._removeOutstandingRequest(request));
    return request;
  }
};
ViewportSemanticTokensContribution.ID = "editor.contrib.viewportSemanticTokens";
ViewportSemanticTokensContribution = __decorate([
  __param(1, model.IModelService),
  __param(2, themeService.IThemeService),
  __param(3, configuration.IConfigurationService),
  __param(4, languageFeatureDebounce.ILanguageFeatureDebounceService),
  __param(5, languageFeatures.ILanguageFeaturesService)
], ViewportSemanticTokensContribution);
editorExtensions.registerEditorContribution(ViewportSemanticTokensContribution.ID, ViewportSemanticTokensContribution);
