import { AstUtils, GrammarUtils } from "langium";
import { hasLeadingSlash, hasProtocol, isRelative, withoutBase, withoutLeadingSlash } from "ufo";
import { ast, isParsedLikeC4LangiumDocument } from "../ast.js";
import { logWarnError } from "../logger.js";
export class LikeC4DocumentLinkProvider {
  constructor(services) {
    this.services = services;
  }
  getDocumentLinks(doc, _params) {
    if (!isParsedLikeC4LangiumDocument(doc)) {
      return [];
    }
    return AstUtils.streamAllContents(doc.parseResult.value).filter(ast.isLinkProperty).map((n) => {
      try {
        const range = GrammarUtils.findNodeForProperty(n.$cstNode, "value")?.range;
        const target = this.resolveLink(doc, n.value);
        if (range && hasProtocol(target)) {
          return {
            range,
            target
          };
        }
      } catch (e) {
        logWarnError(e);
      }
      return null;
    }).nonNullable().toArray();
  }
  resolveLink(doc, link) {
    if (hasProtocol(link) || hasLeadingSlash(link)) {
      return link;
    }
    const base = isRelative(link) ? new URL(doc.uri.toString(true)) : this.services.shared.workspace.WorkspaceManager.workspaceURL;
    return new URL(link, base).toString();
  }
  relativeLink(doc, link) {
    if (hasLeadingSlash(link)) {
      return withoutLeadingSlash(link);
    }
    if (isRelative(link)) {
      const base = new URL(doc.uri.toString(true));
      const linkURL = new URL(link, base).toString();
      return withoutLeadingSlash(
        withoutBase(linkURL, this.services.shared.workspace.WorkspaceManager.workspaceURL.toString())
      );
    }
    return null;
  }
}
