import { Emitter, Listener } from 'fancy-emitter';
import type { Name, LobbyID } from '@mothepro/signaling-lobby';
import { SimpleClient } from './Client.js';
import { MySimplePeer, Sendable } from './Peer.js';
/** Represent where we are in the process of connecting to some peers. */
export declare const enum State {
    /** Still attempting to connect to the server. */
    OFFLINE = 0,
    /** We are now connected to the server in lobby, waiting to make a group or join a group. */
    LOBBY = 1,
    /** We have accepted a group and trying to make the RTCs. */
    LOADING = 2,
    /** The connections with peers are set and we can now broadcast messages. */
    READY = 3
}
export default class<T extends Sendable = Sendable> {
    readonly state: State;
    /** Activated when the state changes, Cancels when finalized, Deactivates when error is throw. */
    readonly stateChange: Emitter<State>;
    /** Activated when a client joins the lobby. */
    readonly lobbyConnection: Listener<SimpleClient>;
    /** The peers who's connections are still open */
    readonly peers: MySimplePeer<T>[];
    /** Generator for random integers that will be consistent across connections within [-2 ** 31, 2 ** 31). */
    private rng?;
    private readonly server;
    protected assert(valid: State, message?: string): true;
    /**
     * Generates a random number in [0,1), same as Math.random()
     * If `isInt` is true, then an integer in range [-2 ** 31, 2 ** 31) is generated instead.
     *
     * `state` must be `State.READY`.
     */
    readonly random: (isInt?: boolean) => number;
    /**
     * Propose a group with other clients connected to this lobby.
     *
     * `state` must be `State.LOBBY`.
     */
    readonly proposeGroup: (...members: SimpleClient[]) => void;
    /**
     * Whether a group with the following memebers has been proposed or answered.
     *
     * `state` must be `State.LOBBY`.
     */
    readonly groupExists: (...members: SimpleClient[]) => boolean;
    /**
     * Send data to all connected peers.
     *
     * `state` must be `State.READY`.
     */
    readonly broadcast: (data: T, includeSelf?: boolean) => void;
    constructor({ name, stuns, lobby, server: { address, version }, fallback, retries, timeout }: {
        /** Name used to connect to lobby with */
        name: Name;
        /** STUN servers to use to initialize P2P connections */
        stuns: string[];
        /** Lobby ID to use for this app */
        lobby: LobbyID;
        /** Settings for the signaling server */
        server: {
            /** The address of the signaling server */
            address: URL | string;
            /** The version of `@mothepro/signaling-lobby` the signaling server is running */
            version: string;
        };
        /** Whether to use the signaling server as a fallback when a direct connection to peer can not be established. */
        fallback?: boolean;
        /** Number of times to attempt to make an RTC connection, if negative direct p2p connections will not be attempted. Defaults to 1 */
        retries?: number;
        /** The number of milliseconds to wait before giving up on the connection. Doesn't give up by default */
        timeout?: number;
    });
    private bindServerState;
}
