import { append, $ as $$1 } from "../../../../base/browser/dom.mjs";
import { asArray } from "../../../../base/common/arrays.mjs";
import { AsyncIterableObject } from "../../../../base/common/async.mjs";
import { MarkdownString, isEmptyMarkdownString } from "../../../../base/common/htmlContent.mjs";
import { DisposableStore } from "../../../../base/common/lifecycle.mjs";
import { MarkdownRenderer } from "../../markdownRenderer/browser/markdownRenderer.mjs";
import { Position } from "../../../common/core/position.mjs";
import { Range } from "../../../common/core/range.mjs";
import { ILanguageService } from "../../../common/languages/language.mjs";
import { getHover } from "./getHover.mjs";
import { localize } from "../../../../nls.mjs";
import { IConfigurationService } from "../../../../platform/configuration/common/configuration.mjs";
import { IOpenerService } from "../../../../platform/opener/common/opener.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);
  };
};
const $ = $$1;
class MarkdownHover {
  constructor(owner, range, contents, ordinal) {
    this.owner = owner;
    this.range = range;
    this.contents = contents;
    this.ordinal = ordinal;
  }
  isValidForHoverAnchor(anchor) {
    return anchor.type === 1 && this.range.startColumn <= anchor.range.startColumn && this.range.endColumn >= anchor.range.endColumn;
  }
}
let MarkdownHoverParticipant = class MarkdownHoverParticipant2 {
  constructor(_editor, _languageService, _openerService, _configurationService, _languageFeaturesService) {
    this._editor = _editor;
    this._languageService = _languageService;
    this._openerService = _openerService;
    this._configurationService = _configurationService;
    this._languageFeaturesService = _languageFeaturesService;
    this.hoverOrdinal = 2;
  }
  createLoadingMessage(anchor) {
    return new MarkdownHover(this, anchor.range, [new MarkdownString().appendText(localize("modesContentHover.loading", "Loading..."))], 2e3);
  }
  computeSync(anchor, lineDecorations) {
    if (!this._editor.hasModel() || anchor.type !== 1) {
      return [];
    }
    const model = this._editor.getModel();
    const lineNumber = anchor.range.startLineNumber;
    const maxColumn = model.getLineMaxColumn(lineNumber);
    const result = [];
    let index = 1e3;
    const lineLength = model.getLineLength(lineNumber);
    const languageId = model.getLanguageIdAtPosition(anchor.range.startLineNumber, anchor.range.startColumn);
    const maxTokenizationLineLength = this._configurationService.getValue("editor.maxTokenizationLineLength", {
      overrideIdentifier: languageId
    });
    if (typeof maxTokenizationLineLength === "number" && lineLength >= maxTokenizationLineLength) {
      result.push(new MarkdownHover(this, anchor.range, [{
        value: localize("too many characters", "Tokenization is skipped for long lines for performance reasons. This can be configured via `editor.maxTokenizationLineLength`.")
      }], index++));
    }
    for (const d of lineDecorations) {
      const startColumn = d.range.startLineNumber === lineNumber ? d.range.startColumn : 1;
      const endColumn = d.range.endLineNumber === lineNumber ? d.range.endColumn : maxColumn;
      const hoverMessage = d.options.hoverMessage;
      if (!hoverMessage || isEmptyMarkdownString(hoverMessage)) {
        continue;
      }
      const range = new Range(anchor.range.startLineNumber, startColumn, anchor.range.startLineNumber, endColumn);
      result.push(new MarkdownHover(this, range, asArray(hoverMessage), index++));
    }
    return result;
  }
  computeAsync(anchor, lineDecorations, token) {
    if (!this._editor.hasModel() || anchor.type !== 1) {
      return AsyncIterableObject.EMPTY;
    }
    const model = this._editor.getModel();
    if (!this._languageFeaturesService.hoverProvider.has(model)) {
      return AsyncIterableObject.EMPTY;
    }
    const position = new Position(anchor.range.startLineNumber, anchor.range.startColumn);
    return getHover(this._languageFeaturesService.hoverProvider, model, position, token).filter((item) => !isEmptyMarkdownString(item.hover.contents)).map((item) => {
      const rng = item.hover.range ? Range.lift(item.hover.range) : anchor.range;
      return new MarkdownHover(this, rng, item.hover.contents, item.ordinal);
    });
  }
  renderHoverParts(context, hoverParts) {
    return renderMarkdownHovers(context, hoverParts, this._editor, this._languageService, this._openerService);
  }
};
MarkdownHoverParticipant = __decorate([
  __param(1, ILanguageService),
  __param(2, IOpenerService),
  __param(3, IConfigurationService),
  __param(4, ILanguageFeaturesService)
], MarkdownHoverParticipant);
function renderMarkdownHovers(context, hoverParts, editor, languageService, openerService) {
  hoverParts.sort((a, b) => a.ordinal - b.ordinal);
  const disposables = new DisposableStore();
  for (const hoverPart of hoverParts) {
    for (const contents of hoverPart.contents) {
      if (isEmptyMarkdownString(contents)) {
        continue;
      }
      const markdownHoverElement = $("div.hover-row.markdown-hover");
      const hoverContentsElement = append(markdownHoverElement, $("div.hover-contents"));
      const renderer = disposables.add(new MarkdownRenderer({ editor }, languageService, openerService));
      disposables.add(renderer.onDidRenderAsync(() => {
        hoverContentsElement.className = "hover-contents code-hover-contents";
        context.onContentsChanged();
      }));
      const renderedContents = disposables.add(renderer.render(contents));
      hoverContentsElement.appendChild(renderedContents.element);
      context.fragment.appendChild(markdownHoverElement);
    }
  }
  return disposables;
}
export {
  MarkdownHover,
  MarkdownHoverParticipant,
  renderMarkdownHovers
};
