import { RunOnceScheduler, createCancelablePromise } from "../../../../base/common/async.mjs";
import { Disposable } from "../../../../base/common/lifecycle.mjs";
import { registerEditorContribution } from "../../../browser/editorExtensions.mjs";
import { hasDocumentRangeSemanticTokensProvider, getDocumentRangeSemanticTokens } from "../../../common/services/getSemanticTokens.mjs";
import { IModelService } from "../../../common/services/model.mjs";
import { SEMANTIC_HIGHLIGHTING_SETTING_ID, isSemanticColoringEnabled } from "../../../common/services/modelService.mjs";
import { toMultilineTokens2 } from "../../../common/services/semanticTokensProviderStyling.mjs";
import { IConfigurationService } from "../../../../platform/configuration/common/configuration.mjs";
import { IThemeService } from "../../../../platform/theme/common/themeService.mjs";
import { ILanguageFeatureDebounceService } from "../../../common/services/languageFeatureDebounce.mjs";
import { StopWatch } from "../../../../base/common/stopwatch.mjs";
import { ILanguageFeaturesService } from "../../../common/services/languageFeatures.mjs";
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 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 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(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 model = this._editor.getModel();
    if (model.hasCompleteSemanticTokens()) {
      return;
    }
    if (!isSemanticColoringEnabled(model, this._themeService, this._configurationService)) {
      if (model.hasSomeSemanticTokens()) {
        model.setSemanticTokens(null, false);
      }
      return;
    }
    if (!hasDocumentRangeSemanticTokensProvider(this._provider, model)) {
      if (model.hasSomeSemanticTokens()) {
        model.setSemanticTokens(null, false);
      }
      return;
    }
    const visibleRanges = this._editor.getVisibleRangesPlusViewportAboveBelow();
    this._outstandingRequests = this._outstandingRequests.concat(visibleRanges.map((range) => this._requestRange(model, range)));
  }
  _requestRange(model, range) {
    const requestVersionId = model.getVersionId();
    const request = createCancelablePromise((token) => Promise.resolve(getDocumentRangeSemanticTokens(this._provider, model, range, token)));
    const sw = new StopWatch(false);
    request.then((r) => {
      this._debounceInformation.update(model, sw.elapsed());
      if (!r || !r.tokens || model.isDisposed() || model.getVersionId() !== requestVersionId) {
        return;
      }
      const { provider, tokens: result } = r;
      const styling = this._modelService.getSemanticTokensProviderStyling(provider);
      model.setPartialSemanticTokens(range, toMultilineTokens2(result, styling, model.getLanguageId()));
    }).then(() => this._removeOutstandingRequest(request), () => this._removeOutstandingRequest(request));
    return request;
  }
};
ViewportSemanticTokensContribution.ID = "editor.contrib.viewportSemanticTokens";
ViewportSemanticTokensContribution = __decorate([
  __param(1, IModelService),
  __param(2, IThemeService),
  __param(3, IConfigurationService),
  __param(4, ILanguageFeatureDebounceService),
  __param(5, ILanguageFeaturesService)
], ViewportSemanticTokensContribution);
registerEditorContribution(ViewportSemanticTokensContribution.ID, ViewportSemanticTokensContribution);
