import { AsyncIterableObject } from "../../../../base/common/async.mjs";
import { CancellationToken } from "../../../../base/common/cancellation.mjs";
import { onUnexpectedExternalError } from "../../../../base/common/errors.mjs";
import { registerModelAndPositionCommand } from "../../../browser/editorExtensions.mjs";
import { ILanguageFeaturesService } from "../../../common/services/languageFeatures.mjs";
var __awaiter = globalThis && globalThis.__awaiter || function(thisArg, _arguments, P, generator) {
  function adopt(value) {
    return value instanceof P ? value : new P(function(resolve) {
      resolve(value);
    });
  }
  return new (P || (P = Promise))(function(resolve, reject) {
    function fulfilled(value) {
      try {
        step(generator.next(value));
      } catch (e) {
        reject(e);
      }
    }
    function rejected(value) {
      try {
        step(generator["throw"](value));
      } catch (e) {
        reject(e);
      }
    }
    function step(result) {
      result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
    }
    step((generator = generator.apply(thisArg, _arguments || [])).next());
  });
};
class HoverProviderResult {
  constructor(provider, hover, ordinal) {
    this.provider = provider;
    this.hover = hover;
    this.ordinal = ordinal;
  }
}
function executeProvider(provider, ordinal, model, position, token) {
  return __awaiter(this, void 0, void 0, function* () {
    try {
      const result = yield Promise.resolve(provider.provideHover(model, position, token));
      if (result && isValid(result)) {
        return new HoverProviderResult(provider, result, ordinal);
      }
    } catch (err) {
      onUnexpectedExternalError(err);
    }
    return void 0;
  });
}
function getHover(registry, model, position, token) {
  const providers = registry.ordered(model);
  const promises = providers.map((provider, index) => executeProvider(provider, index, model, position, token));
  return AsyncIterableObject.fromPromises(promises).coalesce();
}
function getHoverPromise(registry, model, position, token) {
  return getHover(registry, model, position, token).map((item) => item.hover).toPromise();
}
registerModelAndPositionCommand("_executeHoverProvider", (accessor, model, position) => {
  const languageFeaturesService = accessor.get(ILanguageFeaturesService);
  return getHoverPromise(languageFeaturesService.hoverProvider, model, position, CancellationToken.None);
});
function isValid(result) {
  const hasRange = typeof result.range !== "undefined";
  const hasHtmlContent = typeof result.contents !== "undefined" && result.contents && result.contents.length > 0;
  return hasRange && hasHtmlContent;
}
export {
  HoverProviderResult,
  getHover,
  getHoverPromise
};
