"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const dom = require("../../../../base/browser/dom.js");
const arrays = require("../../../../base/common/arrays.js");
const async = require("../../../../base/common/async.js");
const errors = require("../../../../base/common/errors.js");
const lifecycle = require("../../../../base/common/lifecycle.js");
const resources = require("../../../../base/common/resources.js");
const range = require("../../../common/core/range.js");
const markerDecorations = require("../../../common/services/markerDecorations.js");
const codeAction = require("../../codeAction/browser/codeAction.js");
const codeActionCommands = require("../../codeAction/browser/codeActionCommands.js");
const types = require("../../codeAction/browser/types.js");
const gotoError = require("../../gotoError/browser/gotoError.js");
const nls = require("../../../../nls.js");
const markers = require("../../../../platform/markers/common/markers.js");
const opener = require("../../../../platform/opener/common/opener.js");
const progress = require("../../../../platform/progress/common/progress.js");
const colorRegistry = require("../../../../platform/theme/common/colorRegistry.js");
const themeService = require("../../../../platform/theme/common/themeService.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);
  };
};
const $ = dom.$;
class MarkerHover {
  constructor(owner, range2, marker) {
    this.owner = owner;
    this.range = range2;
    this.marker = marker;
  }
  isValidForHoverAnchor(anchor) {
    return anchor.type === 1 && this.range.startColumn <= anchor.range.startColumn && this.range.endColumn >= anchor.range.endColumn;
  }
}
const markerCodeActionTrigger = {
  type: 1,
  filter: { include: types.CodeActionKind.QuickFix }
};
exports.MarkerHoverParticipant = class MarkerHoverParticipant {
  constructor(_editor, _markerDecorationsService, _openerService, _languageFeaturesService) {
    this._editor = _editor;
    this._markerDecorationsService = _markerDecorationsService;
    this._openerService = _openerService;
    this._languageFeaturesService = _languageFeaturesService;
    this.hoverOrdinal = 5;
    this.recentMarkerCodeActionsInfo = void 0;
  }
  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 = [];
    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 marker = this._markerDecorationsService.getMarker(model.uri, d);
      if (!marker) {
        continue;
      }
      const range$1 = new range.Range(anchor.range.startLineNumber, startColumn, anchor.range.startLineNumber, endColumn);
      result.push(new MarkerHover(this, range$1, marker));
    }
    return result;
  }
  renderHoverParts(context, hoverParts) {
    if (!hoverParts.length) {
      return lifecycle.Disposable.None;
    }
    const disposables = new lifecycle.DisposableStore();
    hoverParts.forEach((msg) => context.fragment.appendChild(this.renderMarkerHover(msg, disposables)));
    const markerHoverForStatusbar = hoverParts.length === 1 ? hoverParts[0] : hoverParts.sort((a, b) => markers.MarkerSeverity.compare(a.marker.severity, b.marker.severity))[0];
    this.renderMarkerStatusbar(context, markerHoverForStatusbar, disposables);
    return disposables;
  }
  renderMarkerHover(markerHover, disposables) {
    const hoverElement = $("div.hover-row");
    const markerElement = dom.append(hoverElement, $("div.marker.hover-contents"));
    const { source, message, code, relatedInformation } = markerHover.marker;
    this._editor.applyFontInfo(markerElement);
    const messageElement = dom.append(markerElement, $("span"));
    messageElement.style.whiteSpace = "pre-wrap";
    messageElement.innerText = message;
    if (source || code) {
      if (code && typeof code !== "string") {
        const sourceAndCodeElement = $("span");
        if (source) {
          const sourceElement = dom.append(sourceAndCodeElement, $("span"));
          sourceElement.innerText = source;
        }
        const codeLink = dom.append(sourceAndCodeElement, $("a.code-link"));
        codeLink.setAttribute("href", code.target.toString());
        disposables.add(dom.addDisposableListener(codeLink, "click", (e) => {
          this._openerService.open(code.target, { allowCommands: true });
          e.preventDefault();
          e.stopPropagation();
        }));
        const codeElement = dom.append(codeLink, $("span"));
        codeElement.innerText = code.value;
        const detailsElement = dom.append(markerElement, sourceAndCodeElement);
        detailsElement.style.opacity = "0.6";
        detailsElement.style.paddingLeft = "6px";
      } else {
        const detailsElement = dom.append(markerElement, $("span"));
        detailsElement.style.opacity = "0.6";
        detailsElement.style.paddingLeft = "6px";
        detailsElement.innerText = source && code ? `${source}(${code})` : source ? source : `(${code})`;
      }
    }
    if (arrays.isNonEmptyArray(relatedInformation)) {
      for (const { message: message2, resource, startLineNumber, startColumn } of relatedInformation) {
        const relatedInfoContainer = dom.append(markerElement, $("div"));
        relatedInfoContainer.style.marginTop = "8px";
        const a = dom.append(relatedInfoContainer, $("a"));
        a.innerText = `${resources.basename(resource)}(${startLineNumber}, ${startColumn}): `;
        a.style.cursor = "pointer";
        disposables.add(dom.addDisposableListener(a, "click", (e) => {
          e.stopPropagation();
          e.preventDefault();
          if (this._openerService) {
            this._openerService.open(resource, {
              fromUserGesture: true,
              editorOptions: { selection: { startLineNumber, startColumn } }
            }).catch(errors.onUnexpectedError);
          }
        }));
        const messageElement2 = dom.append(relatedInfoContainer, $("span"));
        messageElement2.innerText = message2;
        this._editor.applyFontInfo(messageElement2);
      }
    }
    return hoverElement;
  }
  renderMarkerStatusbar(context, markerHover, disposables) {
    if (markerHover.marker.severity === markers.MarkerSeverity.Error || markerHover.marker.severity === markers.MarkerSeverity.Warning || markerHover.marker.severity === markers.MarkerSeverity.Info) {
      context.statusBar.addAction({
        label: nls.localize("view problem", "View Problem"),
        commandId: gotoError.NextMarkerAction.ID,
        run: () => {
          var _a;
          context.hide();
          (_a = gotoError.MarkerController.get(this._editor)) === null || _a === void 0 ? void 0 : _a.showAtMarker(markerHover.marker);
          this._editor.focus();
        }
      });
    }
    if (!this._editor.getOption(
      81
      /* readOnly */
    )) {
      const quickfixPlaceholderElement = context.statusBar.append($("div"));
      if (this.recentMarkerCodeActionsInfo) {
        if (markers.IMarkerData.makeKey(this.recentMarkerCodeActionsInfo.marker) === markers.IMarkerData.makeKey(markerHover.marker)) {
          if (!this.recentMarkerCodeActionsInfo.hasCodeActions) {
            quickfixPlaceholderElement.textContent = nls.localize("noQuickFixes", "No quick fixes available");
          }
        } else {
          this.recentMarkerCodeActionsInfo = void 0;
        }
      }
      const updatePlaceholderDisposable = this.recentMarkerCodeActionsInfo && !this.recentMarkerCodeActionsInfo.hasCodeActions ? lifecycle.Disposable.None : disposables.add(async.disposableTimeout(() => quickfixPlaceholderElement.textContent = nls.localize("checkingForQuickFixes", "Checking for quick fixes..."), 200));
      if (!quickfixPlaceholderElement.textContent) {
        quickfixPlaceholderElement.textContent = String.fromCharCode(160);
      }
      const codeActionsPromise = this.getCodeActions(markerHover.marker);
      disposables.add(lifecycle.toDisposable(() => codeActionsPromise.cancel()));
      codeActionsPromise.then((actions) => {
        updatePlaceholderDisposable.dispose();
        this.recentMarkerCodeActionsInfo = { marker: markerHover.marker, hasCodeActions: actions.validActions.length > 0 };
        if (!this.recentMarkerCodeActionsInfo.hasCodeActions) {
          actions.dispose();
          quickfixPlaceholderElement.textContent = nls.localize("noQuickFixes", "No quick fixes available");
          return;
        }
        quickfixPlaceholderElement.style.display = "none";
        let showing = false;
        disposables.add(lifecycle.toDisposable(() => {
          if (!showing) {
            actions.dispose();
          }
        }));
        context.statusBar.addAction({
          label: nls.localize("quick fixes", "Quick Fix..."),
          commandId: codeActionCommands.QuickFixAction.Id,
          run: (target) => {
            showing = true;
            const controller = codeActionCommands.QuickFixController.get(this._editor);
            const elementPosition = dom.getDomNodePagePosition(target);
            context.hide();
            controller === null || controller === void 0 ? void 0 : controller.showCodeActions(markerCodeActionTrigger, actions, {
              x: elementPosition.left + 6,
              y: elementPosition.top + elementPosition.height + 6
            });
          }
        });
      }, errors.onUnexpectedError);
    }
  }
  getCodeActions(marker) {
    return async.createCancelablePromise((cancellationToken) => {
      return codeAction.getCodeActions(this._languageFeaturesService.codeActionProvider, this._editor.getModel(), new range.Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn), markerCodeActionTrigger, progress.Progress.None, cancellationToken);
    });
  }
};
exports.MarkerHoverParticipant = __decorate([
  __param(1, markerDecorations.IMarkerDecorationsService),
  __param(2, opener.IOpenerService),
  __param(3, languageFeatures.ILanguageFeaturesService)
], exports.MarkerHoverParticipant);
themeService.registerThemingParticipant((theme, collector) => {
  const linkFg = theme.getColor(colorRegistry.textLinkForeground);
  if (linkFg) {
    collector.addRule(`.monaco-hover .hover-contents a.code-link span { color: ${linkFg}; }`);
  }
  const activeLinkFg = theme.getColor(colorRegistry.textLinkActiveForeground);
  if (activeLinkFg) {
    collector.addRule(`.monaco-hover .hover-contents a.code-link span:hover { color: ${activeLinkFg}; }`);
  }
});
exports.MarkerHover = MarkerHover;
