import { type JsonCompatibleValue, type MaybePromise, type PartialWithUndefined, type Uuid } from '@augment-vir/common';
import { type RequireExactlyOne } from 'type-fest';
import { ListenTarget } from 'typed-event-target';
import { type MultiplayerApi } from '../multiplayer-service/multiplayer-api.js';
import { type MultiplayerService } from '../multiplayer-service/multiplayer-service.js';
import { MultiplayerWebSocketMessageType } from './web-rtc-communication.js';
declare const WebrtcMultiplayerMessageEvent_base: (new (eventInitDict: {
    bubbles?: boolean;
    cancelable?: boolean;
    composed?: boolean;
    detail: any;
}) => import("typed-event-target").TypedCustomEvent<any, "webrtc-multiplayer-message">) & Pick<{
    new (type: string, eventInitDict?: EventInit): Event;
    prototype: Event;
    readonly NONE: 0;
    readonly CAPTURING_PHASE: 1;
    readonly AT_TARGET: 2;
    readonly BUBBLING_PHASE: 3;
}, "prototype" | "NONE" | "CAPTURING_PHASE" | "AT_TARGET" | "BUBBLING_PHASE"> & Pick<import("typed-event-target").TypedCustomEvent<any, "webrtc-multiplayer-message">, "type">;
/**
 * An event that is omitted from {@link WebrtcController} when a WebRTC message is received.
 *
 * @category Internal
 */
export declare class WebrtcMultiplayerMessageEvent<MessageData extends JsonCompatibleValue> extends WebrtcMultiplayerMessageEvent_base {
    readonly sourceClientId: Uuid;
    detail: MessageData;
    constructor(sourceClientId: Uuid, detail: MessageData);
}
/**
 * Type for data in {@link WebrtcMultiplayerConnectionUpdateEvent}.
 *
 * @category Internal
 */
export type MultiplayerConnectionUpdate = RequireExactlyOne<{
    newHost: Uuid;
    newMember: Uuid;
    lostHost: Uuid;
    lostMember: Uuid;
}>;
declare const WebrtcMultiplayerConnectionUpdateEvent_base: (new (eventInitDict: {
    bubbles?: boolean;
    cancelable?: boolean;
    composed?: boolean;
    detail: import("type-fest/source/require-exactly-one.js")._RequireExactlyOne<{
        newHost: Uuid;
        newMember: Uuid;
        lostHost: Uuid;
        lostMember: Uuid;
    }, "newHost" | "newMember" | "lostHost" | "lostMember">;
}) => import("typed-event-target").TypedCustomEvent<import("type-fest/source/require-exactly-one.js")._RequireExactlyOne<{
    newHost: Uuid;
    newMember: Uuid;
    lostHost: Uuid;
    lostMember: Uuid;
}, "newHost" | "newMember" | "lostHost" | "lostMember">, "webrtc-multiplayer-connection-update">) & Pick<{
    new (type: string, eventInitDict?: EventInit): Event;
    prototype: Event;
    readonly NONE: 0;
    readonly CAPTURING_PHASE: 1;
    readonly AT_TARGET: 2;
    readonly BUBBLING_PHASE: 3;
}, "prototype" | "NONE" | "CAPTURING_PHASE" | "AT_TARGET" | "BUBBLING_PHASE"> & Pick<import("typed-event-target").TypedCustomEvent<import("type-fest/source/require-exactly-one.js")._RequireExactlyOne<{
    newHost: Uuid;
    newMember: Uuid;
    lostHost: Uuid;
    lostMember: Uuid;
}, "newHost" | "newMember" | "lostHost" | "lostMember">, "webrtc-multiplayer-connection-update">, "type">;
/**
 * An event that is omitted from {@link WebrtcMultiplayerController} when the multiplayer room host
 * is updated.
 *
 * @category Internal
 */
export declare class WebrtcMultiplayerConnectionUpdateEvent extends WebrtcMultiplayerConnectionUpdateEvent_base {
}
/**
 * A helper for creating a new empty room.
 *
 * @category Internal
 */
export declare function createNewRoom(params?: Readonly<PartialWithUndefined<Omit<RoomInput, 'roomId'>>>): RoomInput;
/**
 * Room selection input for {@link WebrtcMultiplayerController}.
 *
 * @category Internal
 */
export type RoomInput = Pick<Extract<MultiplayerService['webSockets']['/connect']['MessageFromClientType'], {
    type: MultiplayerWebSocketMessageType.Offer;
}>, 'roomPassword' | 'roomId' | 'roomName'>;
/**
 * This is used to check if a new WebRTC connection should be allowed. This will only be triggered
 * on a room host client. Return `true`
 *
 * @category Internal
 */
export type ShouldAllowConnectionCheck<Controller> = (data: {
    connectingClientId: Uuid;
    controller: Controller;
}) => MaybePromise<boolean>;
/**
 * A controller that connects to the multiplayer api and establishes a WebRTC connection to the
 * selected room, or, if the room does not exist yet, creates the room and becomes the host.
 *
 * Make sure, after constructing this class, to call
 * {@link WebrtcMultiplayerController.initConnection} when you're ready to being the connection.
 *
 * @category Internal
 */
export declare class WebrtcMultiplayerController<MessageData extends JsonCompatibleValue = any> extends ListenTarget<WebrtcMultiplayerMessageEvent<MessageData> | WebrtcMultiplayerConnectionUpdateEvent> {
    private readonly gameId;
    private readonly multiplayerApi;
    /**
     * - 'stun.l.google.com:19302'
     * - 'stun.stunprotocol.org'
     * - 'stun.cloudflare.com:3478'
     */
    readonly stunServerUrls: ReadonlyArray<string>;
    readonly multiplayerRoom: Readonly<RoomInput>;
    /** The randomized client id for this controller and client. */
    readonly clientId: Uuid;
    /**
     * This is fired when a WebRTC peer attempts to connect to the host client (this will only
     * be fired if your client is the host). Return `true` to accept the connection. Return
     * `false` to reject it.
     *
     * @default accept all connections
     */
    private readonly shouldAllowConnectionCheck;
    readonly hostClientId: Uuid | undefined;
    /**
     * Connections between multiple WebRTC peers.
     *
     * A connection with the current client's id is the init connection.
     */
    private connections;
    private webSocket;
    private readonly clientSecret;
    readonly isDestroyed: boolean;
    constructor(gameId: string, multiplayerApi: Readonly<MultiplayerApi>, 
    /**
     * - 'stun.l.google.com:19302'
     * - 'stun.stunprotocol.org'
     * - 'stun.cloudflare.com:3478'
     */
    stunServerUrls: ReadonlyArray<string>, multiplayerRoom: Readonly<RoomInput>, 
    /** The randomized client id for this controller and client. */
    clientId?: Uuid, 
    /**
     * This is fired when a WebRTC peer attempts to connect to the host client (this will only
     * be fired if your client is the host). Return `true` to accept the connection. Return
     * `false` to reject it.
     *
     * @default accept all connections
     */
    shouldAllowConnectionCheck?: ShouldAllowConnectionCheck<WebrtcMultiplayerController<MessageData>>);
    /**
     * If this controller is the host, it'll behave differently:
     *
     * - Hosts hold WebRTC connections to all clients (non-hosts only hold a WebRTC connection to the
     *   host).
     * - Hosts hold a WebSocket connection to the signal server so they can receive more clients at
     *   any time.
     */
    isHost(): boolean;
    /**
     * Get all connected client ids.
     *
     * - For host clients, this will indicate how many member clients are connected to the host
     *   client, _not_ including the host itself.
     * - For non-host clients, this will only list the host's client.
     *
     * For host clients, this does ont include the host client id whereas
     * {@link WebrtcMultiplayerController.getAllClientIds} does.
     */
    getConnectedClientIds(): Uuid[];
    /**
     * Get all room client ids.
     *
     * - For host clients, this will indicate how many clients are connected to the room, including
     *   the host client itself.
     * - For non-host clients, this will only list the host's client.
     *
     * For host clients, this includes the host client id whereas
     * {@link WebrtcMultiplayerController.getConnectedClientIds} does not.
     */
    getAllClientIds(): Uuid[];
    /** Indicates whether ths client is connected to a multiplayer room. */
    isConnected(): boolean;
    /** Destroy this controller and clean everything up. */
    destroy(): void;
    /**
     * Send a message to the room participants.
     *
     * - If the current client is the room host, this message is sent to all other room clients.
     * - If the current client is just a room member (not the host), the message is sent to the host.
     */
    sendMessage(data: Readonly<MessageData>): void;
    /** Send a message to just a single client. This is only allowed on a host client. */
    sendToOnlyOneClient(clientId: Uuid, data: Readonly<MessageData>): void;
    /**
     * Call this to connect to the multiplayer server.
     *
     * @returns Whether or not the connection was initialized (it won't be initialized, for example,
     *   if the WebRTC connections already exist).
     */
    initConnection(): Promise<boolean>;
    private sendHostPing;
    private connectionQueue;
    private setupWebSocket;
    private createNewConnection;
}
export {};
