import { Temporal } from "@js-temporal/polyfill";
import { URLPattern } from "urlpattern-polyfill";
import { GetUserAgentOptions } from "./docloader-Q42SMRIB.js";

//#region nodeinfo/semver.d.ts
/**
 * A SemVer object parsed into its constituent parts.
 * @since 1.2.0
 */
interface SemVer {
  /** The major version */
  major: number;
  /** The minor version */
  minor: number;
  /** The patch version */
  patch: number;
  /**
   * The prerelease version
   *
   * @default {[]}
   */
  prerelease?: (string | number)[];
  /**
   * The build metadata
   *
   * @default {[]}
   */
  build?: string[];
}
/**
 * Attempt to parse a string as a semantic version, returning a SemVer object.
 *
 * @example Usage
 * ```ts
 * import { parseSemVer } from "@fedify/fedify/nodeinfo";
 * import { assertEquals } from "@std/assert";
 *
 * const version = parseSemVer("1.2.3");
 * assertEquals(version, {
 *   major: 1,
 *   minor: 2,
 *   patch: 3,
 *   prerelease: [],
 *   build: [],
 * });
 * ```
 *
 * @throws {TypeError} If the input string is invalid.
 * @param value The version string to parse
 * @returns A valid SemVer
 * @since 1.2.0
 */
declare function parseSemVer(value: string): SemVer;
/**
 * Format a SemVer object into a string.
 *
 * @example Usage
 * ```ts
 * import { formatSemVer } from "@fedify/fedify/nodeinfo";
 * import { assertEquals } from "@std/assert";
 *
 * const semver = {
 *   major: 1,
 *   minor: 2,
 *   patch: 3,
 * };
 * assertEquals(formatSemVer(semver), "1.2.3");
 * ```
 *
 * @param version The SemVer to format
 * @returns The string representation of a semantic version.
 * @since 1.2.0
 */
declare function formatSemVer(version: SemVer): string;
//#endregion
//#region nodeinfo/types.d.ts
/**
 * The type of the result of parsing JSON.
 */
type JsonValue = {
  [key: string]: JsonValue | undefined;
} | JsonValue[] | string | number | boolean | null;
/**
 * A NodeInfo object as defined in the NodeInfo 2.1 schema.
 */
interface NodeInfo {
  /**
   * Metadata about server software in use.
   */
  software: Software;
  /**
   * The protocols supported on this server.  At least one protocol must be
   * supported.
   */
  protocols: Protocol[];
  /**
   * The third party sites this server can connect to via their application API.
   */
  services?: Services;
  /**
   * Whether this server allows open self-registration.  Defaults to `false`.
   */
  openRegistrations?: boolean;
  /**
   * Usage statistics for this server.
   */
  usage: Usage;
  /**
   * Free form key value pairs for software specific values.
   * Clients should not rely on any specific key present.
   */
  metadata?: Record<string, JsonValue>;
}
/**
 * Metadata about server software in use.
 */
interface Software {
  /**
   * The canonical name of this server software.  This must comply with
   * pattern `/^[a-z0-9-]+$/`.
   */
  name: string;
  /**
   * The version of this server software.
   * @see {@link parseSemVer}
   */
  version: SemVer;
  /**
   * The URL of the source code repository of this server software.
   */
  repository?: URL;
  /**
   * The URL of the homepage of this server software.
   */
  homepage?: URL;
}
/**
 * The protocols supported on this server.
 */
type Protocol = "activitypub" | "buddycloud" | "dfrn" | "diaspora" | "libertree" | "ostatus" | "pumpio" | "tent" | "xmpp" | "zot";
/**
 * The third party sites this server can connect to via their application API.
 */
interface Services {
  /**
   * The third party sites this server can retrieve messages from for combined
   * display with regular traffic.
   */
  inbound?: InboundService[];
  /**
   * The third party sites this server can publish messages to on the behalf
   * of a user.
   */
  outbound?: OutboundService[];
}
/**
 * The third party sites this server can retrieve messages from for combined
 * display with regular traffic.
 */
type InboundService = "atom1.0" | "gnusocial" | "imap" | "pnut" | "pop3" | "pumpio" | "rss2.0" | "twitter";
/**
 * The third party sites this server can publish messages to on the behalf
 * of a user.
 */
type OutboundService = "atom1.0" | "blogger" | "buddycloud" | "diaspora" | "dreamwidth" | "drupal" | "facebook" | "friendica" | "gnusocial" | "google" | "insanejournal" | "libertree" | "linkedin" | "livejournal" | "mediagoblin" | "myspace" | "pinterest" | "pnut" | "posterous" | "pumpio" | "redmatrix" | "rss2.0" | "smtp" | "tent" | "tumblr" | "twitter" | "wordpress" | "xmpp";
/**
 * Usage statistics for this server.
 */
interface Usage {
  /**
   * Statistics about the users of this server.
   */
  users: {
    /**
     * The total amount of on this server registered users.  This number
     * has to be an integer greater than or equal to zero.
     */
    total?: number;
    /**
     * The amount of users that signed in at least once in the last 180 days.
     * This number has to be an integer greater than or equal to zero.
     */
    activeHalfyear?: number;
    /**
     * The amount of users that signed in at least once in the last 30 days.
     * This number has to be an integer greater than or equal to zero.
     */
    activeMonth?: number;
  };
  /**
   * The amount of posts that were made by users that are registered on this
   * server.  This number has to be an integer greater than or equal to zero.
   */
  localPosts: number;
  /**
   * The amount of comments that were made by users that are registered on this
   * server.  This number has to be an integer greater than or equal to zero.
   */
  localComments: number;
}
/**
 * Converts a {@link NodeInfo} object to a JSON value.
 * @param nodeInfo The {@link NodeInfo} object to convert.
 * @returns The JSON value that complies with the NodeInfo schema.
 * @throws {TypeError} If the {@link NodeInfo} object is invalid.
 */
declare function nodeInfoToJson(nodeInfo: NodeInfo): JsonValue;
//#endregion
//#region nodeinfo/client.d.ts
/**
 * Options for {@link getNodeInfo} function.
 * @since 1.2.0
 */
interface GetNodeInfoOptions {
  /**
   * Whether to directly fetch the NodeInfo document from the given URL.
   * Otherwise, the NodeInfo document will be fetched from the `.well-known`
   * location of the given URL.
   *
   * Turned off by default.
   */
  direct?: boolean;
  /**
   * How strictly to parse the NodeInfo document.
   *
   *  -  `"strict"`: Parse the NodeInfo document strictly.  If the document is
   *     invalid, `undefined` is returned.  This is the default.
   *  -  `"best-effort"`: Try to parse the NodeInfo document even if it is
   *     invalid.
   *  -  `"none"`: Do not parse the NodeInfo document.  The function will return
   *     the raw JSON value.
   */
  parse?: "strict" | "best-effort" | "none";
  /**
   * The options for making `User-Agent` header.
   * If a string is given, it is used as the `User-Agent` header value.
   * If an object is given, it is passed to {@link getUserAgent} to generate
   * the `User-Agent` header value.
   * @since 1.3.0
   */
  userAgent?: GetUserAgentOptions | string;
}
/**
 * Fetches a NodeInfo document from the given URL.
 * @param url The base URL of the server.  If `options.direct` is turned off
 *            (default), the NodeInfo document will be fetched from
 *            the `.well-known` location of this URL (hence the only origin
 *            of the URL is used).  If `options.direct` is turned on,
 *            the NodeInfo document will be fetched from the given URL.
 * @param options Options for fetching the NodeInfo document.
 * @returns The NodeInfo document if it could be fetched successfully.
 *          Otherwise, `undefined` is returned.
 * @since 1.2.0
 */
declare function getNodeInfo(url: URL | string, options?: GetNodeInfoOptions & {
  parse?: "strict" | "best-effort";
}): Promise<NodeInfo | undefined>;
/**
 * Fetches a NodeInfo document from the given URL.
 * @param url The base URL of the server.  If `options.direct` is turned off
 *            (default), the NodeInfo document will be fetched from
 *            the `.well-known` location of this URL (hence the only origin
 *            of the URL is used).  If `options.direct` is turned on,
 *            the NodeInfo document will be fetched from the given URL.
 * @param options Options for fetching the NodeInfo document.
 * @returns The NodeInfo document if it could be fetched successfully.
 *          Otherwise, `undefined` is returned.
 * @since 1.2.0
 */
declare function getNodeInfo(url: URL | string, options: GetNodeInfoOptions & {
  parse: "none";
}): Promise<JsonValue | undefined>;
/**
 * Options for {@link parseNodeInfo} function.
 * @since 1.2.0
 */
interface ParseNodeInfoOptions {
  /**
   * Whether to try to parse the NodeInfo document even if it is invalid.
   * If turned on, the function will return a best-effort result.
   *
   * Turned off by default.
   */
  tryBestEffort?: boolean;
}
/**
 * Parses a NodeInfo document.
 * @param data A JSON value that complies with the NodeInfo schema.
 * @param options Options for parsing the NodeInfo document.
 * @returns The parsed NodeInfo document if it is valid.  Otherwise, `null`
 *          is returned.
 * @since 1.2.0
 */
declare function parseNodeInfo(data: unknown, options?: ParseNodeInfoOptions): NodeInfo | null;
//#endregion
export { GetNodeInfoOptions, InboundService, JsonValue, NodeInfo, OutboundService, ParseNodeInfoOptions, Protocol, SemVer, Services, Software, Usage, formatSemVer, getNodeInfo, nodeInfoToJson, parseNodeInfo, parseSemVer };