import { PackageId, ServiceInterfaceId, ServiceInterfaceType } from '../types';
import { AddressInfo, Host, Hostname, HostnameInfo } from '../types';
import { Effects } from '../Effects';
import { Watchable } from './Watchable';
export type UrlString = string;
export type HostId = string;
export declare const getHostname: (url: string) => Hostname | null;
/**
 * The kinds of hostnames that can be filtered on.
 *
 * - `'mdns'` — mDNS / Bonjour `.local` hostnames
 * - `'domain'` — any os-managed domain name (matches both `'private-domain'` and `'public-domain'` metadata kinds)
 * - `'ip'` — shorthand for both `'ipv4'` and `'ipv6'`
 * - `'ipv4'` — IPv4 addresses only
 * - `'ipv6'` — IPv6 addresses only
 * - `'localhost'` — loopback addresses (`localhost`, `127.0.0.1`, `::1`)
 * - `'link-local'` — IPv6 link-local addresses (fe80::/10)
 * - `'bridge'` — The LXC bridge interface
 * - `'plugin'` — hostnames provided by a plugin package
 */
type FilterKinds = 'mdns' | 'domain' | 'ip' | 'ipv4' | 'ipv6' | 'localhost' | 'link-local' | 'bridge' | 'plugin';
/**
 * Describes which hostnames to include (or exclude) when filtering a `Filled` address.
 *
 * Every field is optional — omitted fields impose no constraint.
 * Filters are composable: the `.filter()` method intersects successive filters,
 * and the `exclude` field inverts a nested filter.
 */
export type Filter = {
    /** Keep only hostnames with the given visibility. `'public'` = externally reachable, `'private'` = LAN-only. */
    visibility?: 'public' | 'private';
    /** Keep only hostnames whose metadata kind matches. A single kind or array of kinds. `'ip'` expands to `['ipv4','ipv6']`, `'domain'` matches both `'private-domain'` and `'public-domain'`. */
    kind?: FilterKinds | FilterKinds[];
    /** Arbitrary predicate — hostnames for which this returns `false` are excluded. */
    predicate?: (h: HostnameInfo) => boolean;
    /** Keep only plugin hostnames provided by this package. Implies `kind: 'plugin'`. */
    pluginId?: PackageId;
    /** A nested filter whose matches are *removed* from the result (logical NOT). */
    exclude?: Filter;
};
type VisibilityFilter<V extends 'public' | 'private'> = V extends 'public' ? (HostnameInfo & {
    public: true;
}) | VisibilityFilter<Exclude<V, 'public'>> : V extends 'private' ? (HostnameInfo & {
    public: false;
}) | VisibilityFilter<Exclude<V, 'private'>> : never;
type KindFilter<K extends FilterKinds> = K extends 'mdns' ? (HostnameInfo & {
    metadata: {
        kind: 'mdns';
    };
}) | KindFilter<Exclude<K, 'mdns'>> : K extends 'domain' ? (HostnameInfo & {
    metadata: {
        kind: 'private-domain';
    };
}) | (HostnameInfo & {
    metadata: {
        kind: 'public-domain';
    };
}) | KindFilter<Exclude<K, 'domain'>> : K extends 'ipv4' ? (HostnameInfo & {
    metadata: {
        kind: 'ipv4';
    };
}) | KindFilter<Exclude<K, 'ipv4'>> : K extends 'ipv6' ? (HostnameInfo & {
    metadata: {
        kind: 'ipv6';
    };
}) | KindFilter<Exclude<K, 'ipv6'>> : K extends 'plugin' ? (HostnameInfo & {
    metadata: {
        kind: 'plugin';
    };
}) | KindFilter<Exclude<K, 'plugin'>> : K extends 'ip' ? KindFilter<Exclude<K, 'ip'> | 'ipv4' | 'ipv6'> : never;
type FilterReturnTy<F extends Filter> = F extends {
    visibility: infer V extends 'public' | 'private';
} ? VisibilityFilter<V> & FilterReturnTy<Omit<F, 'visibility'>> : F extends {
    kind: (infer K extends FilterKinds) | (infer K extends FilterKinds)[];
} ? KindFilter<K> & FilterReturnTy<Omit<F, 'kind'>> : F extends {
    predicate: (h: HostnameInfo) => h is infer H extends HostnameInfo;
} ? H & FilterReturnTy<Omit<F, 'predicate'>> : F extends {
    exclude: infer E extends Filter;
} ? HostnameInfo extends FilterReturnTy<E> ? HostnameInfo : Exclude<HostnameInfo, FilterReturnTy<E>> : HostnameInfo;
declare const nonLocalFilter: {
    readonly exclude: {
        readonly kind: ("localhost" | "link-local" | "bridge")[];
    };
};
declare const publicFilter: {
    readonly visibility: "public";
};
type Formats = 'hostname-info' | 'urlstring' | 'url';
type FormatReturnTy<F extends Filter, Format extends Formats> = Format extends 'hostname-info' ? FilterReturnTy<F> | FormatReturnTy<F, Exclude<Format, 'hostname-info'>> : Format extends 'url' ? URL | FormatReturnTy<F, Exclude<Format, 'url'>> : Format extends 'urlstring' ? UrlString | FormatReturnTy<F, Exclude<Format, 'urlstring'>> : never;
/**
 * A resolved address with its hostnames already populated, plus helpers
 * for filtering, formatting, and converting hostnames to URLs.
 *
 * Filters are chainable and each call returns a new `Filled` narrowed to the
 * matching subset of hostnames:
 *
 * ```ts
 * addresses.nonLocal                         // exclude localhost & link-local
 * addresses.public                           // only publicly-reachable hostnames
 * addresses.filter({ kind: 'domain' })       // only domain-name hostnames
 * addresses.filter({ visibility: 'private' }) // only LAN-reachable hostnames
 * addresses.nonLocal.filter({ kind: 'ip' })  // chainable — non-local IPs only
 * ```
 */
export type Filled<F extends Filter = {}> = {
    /** The hostnames that survived all applied filters. */
    hostnames: HostnameInfo[];
    /** Convert a single hostname into a fully-formed URL string, applying the address's scheme, username, and suffix. */
    toUrl: (h: HostnameInfo) => UrlString;
    /**
     * Return every hostname in the requested format.
     *
     * - `'urlstring'` (default) — formatted URL strings
     * - `'url'`                 — `URL` objects
     * - `'hostname-info'`       — raw `HostnameInfo` objects
     */
    format: <Format extends Formats = 'urlstring'>(format?: Format) => FormatReturnTy<{}, Format>[];
    /**
     * Apply an arbitrary {@link Filter} and return a new `Filled` containing only
     * the hostnames that match. Filters compose: calling `.filter()` on an
     * already-filtered `Filled` intersects the constraints.
     */
    filter: <NewFilter extends Filter>(filter: NewFilter) => Filled<NewFilter & Filter>;
    /**
     * Apply multiple filters and return hostnames that match **any** of them (union / OR).
     *
     * ```ts
     * addresses.matchesAny([{ kind: 'domain' }, { kind: 'mdns' }])
     * ```
     */
    matchesAny: <NewFilters extends Filter[]>(filters: [...NewFilters]) => Filled<NewFilters[number] & F>;
    /** Shorthand filter that excludes `localhost` and IPv6 link-local addresses — keeps only network-reachable hostnames. */
    nonLocal: Filled<typeof nonLocalFilter & Filter>;
    /** Shorthand filter that keeps only publicly-reachable hostnames (those with `public: true`). */
    public: Filled<typeof publicFilter & Filter>;
};
export type FilledAddressInfo = AddressInfo & Filled;
export type ServiceInterfaceFilled = {
    id: string;
    /** The title of this field to be displayed */
    name: string;
    /** Human readable description, used as tooltip usually */
    description: string;
    /** Whether or not to mask the URIs for this interface. Useful if the URIs contain sensitive information, such as a password, macaroon, or API key */
    masked: boolean;
    /** Information about the host for this binding */
    host: Host | null;
    /** URI information */
    addressInfo: FilledAddressInfo | null;
    /** Indicates if we are a ui/p2p/api for the kind of interface that this is representing */
    type: ServiceInterfaceType;
};
export declare const addressHostToUrl: ({ scheme, sslScheme, username, suffix }: AddressInfo, hostname: HostnameInfo) => UrlString;
/**
 * Filters out localhost and IPv6 link-local hostnames from a list.
 * Equivalent to the `nonLocal` filter on `Filled` addresses.
 */
export declare function filterNonLocal(hostnames: HostnameInfo[]): HostnameInfo[];
export declare const filledAddress: (host: Host, addressInfo: AddressInfo) => FilledAddressInfo;
export declare class GetServiceInterface<Mapped = ServiceInterfaceFilled | null> extends Watchable<ServiceInterfaceFilled | null, Mapped> {
    readonly opts: {
        id: string;
        packageId?: string;
    };
    protected readonly label = "GetServiceInterface";
    constructor(effects: Effects, opts: {
        id: string;
        packageId?: string;
    }, options?: {
        map?: (value: ServiceInterfaceFilled | null) => Mapped;
        eq?: (a: Mapped, b: Mapped) => boolean;
    });
    protected fetch(callback?: () => void): Promise<ServiceInterfaceFilled | null>;
}
export declare function getOwnServiceInterface(effects: Effects, id: ServiceInterfaceId): GetServiceInterface;
export declare function getOwnServiceInterface<Mapped>(effects: Effects, id: ServiceInterfaceId, map: (interfaces: ServiceInterfaceFilled | null) => Mapped, eq?: (a: Mapped, b: Mapped) => boolean): GetServiceInterface<Mapped>;
export declare function getServiceInterface(effects: Effects, opts: {
    id: ServiceInterfaceId;
    packageId: PackageId;
}): GetServiceInterface;
export declare function getServiceInterface<Mapped>(effects: Effects, opts: {
    id: ServiceInterfaceId;
    packageId: PackageId;
}, map: (interfaces: ServiceInterfaceFilled | null) => Mapped, eq?: (a: Mapped, b: Mapped) => boolean): GetServiceInterface<Mapped>;
export {};
