import { EventBus } from '../core/EventBus';
import type { Vec2, EntityId } from '../core/types';
export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'failed';
export interface PeerInfo {
    peerId: string;
    displayName: string;
    state: ConnectionState;
    latencyMs: number;
    /** DataChannel reference */
    channel: RTCDataChannel | null;
    connection: RTCPeerConnection | null;
}
export interface SignalingMessage {
    type: 'offer' | 'answer' | 'ice-candidate' | 'join' | 'leave' | 'room-info';
    from: string;
    to?: string;
    roomId?: string;
    payload: unknown;
}
export type SignalingTransport = {
    send(msg: SignalingMessage): void;
    onMessage: ((msg: SignalingMessage) => void) | null;
    connect(url: string): Promise<void>;
    disconnect(): void;
};
/** Default WebSocket-based signaling transport. */
export declare function createWebSocketSignaling(): SignalingTransport;
export interface RTCConfig {
    iceServers?: RTCIceServer[];
    dataChannelLabel?: string;
    ordered?: boolean;
    maxRetransmits?: number;
}
export declare class PeerManager {
    readonly events: EventBus;
    private peers;
    private localId;
    private rtcConfig;
    private signaling;
    constructor(localId: string, signaling: SignalingTransport, config?: Partial<RTCConfig>);
    get localPeerId(): string;
    get connectedPeers(): PeerInfo[];
    getPeer(id: string): PeerInfo | undefined;
    /** Initiate connection to a remote peer. */
    connectToPeer(remotePeerId: string): Promise<void>;
    private handleSignaling;
    private setupChannel;
    /** Send to a specific peer. */
    sendTo(peerId: string, data: ArrayBuffer | string): void;
    /** Broadcast to all connected peers. */
    broadcast(data: ArrayBuffer | string): void;
    /** Measure latency via ping / pong. */
    ping(peerId: string): void;
    disconnectPeer(peerId: string): void;
    disconnectAll(): void;
}
export type NetworkMode = 'offline' | 'host' | 'client' | 'dedicated';
export interface NetworkIdentity {
    netId: number;
    ownerId: string;
    entityId: EntityId;
}
export interface RPCDef {
    name: string;
    /** 'server' = only host runs it, 'client' = everyone, 'owner' = only the owner */
    target: 'server' | 'client' | 'owner';
}
export interface SyncVarDef {
    entityId: EntityId;
    component: string;
    property: string;
    /** Interpolate on clients (for transforms). */
    interpolate: boolean;
}
export interface NetworkMessage {
    type: 'rpc' | 'sync' | 'spawn' | 'destroy' | 'snapshot' | 'input' | 'ping' | 'pong';
    tick: number;
    senderId: string;
    payload: unknown;
}
export declare class NetworkManager {
    readonly events: EventBus;
    private _mode;
    private _tick;
    private _tickRate;
    private _tickAccumulator;
    private identities;
    private rpcHandlers;
    private syncVars;
    private _nextNetId;
    peers: PeerManager | null;
    get mode(): NetworkMode;
    get tick(): number;
    get tickRate(): number;
    set tickRate(v: number);
    get isHost(): boolean;
    get isOnline(): boolean;
    /** Start as host or client. */
    start(mode: NetworkMode, peerManager: PeerManager): void;
    stop(): void;
    registerEntity(entityId: EntityId, ownerId: string): NetworkIdentity;
    getIdentity(netId: number): NetworkIdentity | undefined;
    getEntityIdentity(entityId: EntityId): NetworkIdentity | undefined;
    registerRPC(name: string, handler: (senderId: string, args: unknown[]) => void): void;
    callRPC(name: string, args: unknown[], target?: 'server' | 'all' | string): void;
    registerSyncVar(def: SyncVarDef): void;
    update(dt: number): void;
    networkSpawn(entityId: EntityId, prefabName: string, position: Vec2): void;
    networkDestroy(netId: number): void;
    private handleMessage;
}
export interface Snapshot {
    tick: number;
    timestamp: number;
    states: Map<number, EntityState>;
}
export interface EntityState {
    netId: number;
    position: Vec2;
    rotation: number;
    velocity: Vec2;
    custom: Record<string, unknown>;
}
/** Snapshot buffer for interpolation / reconciliation. */
export declare class SnapshotBuffer {
    private buffer;
    readonly maxSize: number;
    constructor(maxSize?: number);
    push(snapshot: Snapshot): void;
    /** Get two snapshots bracketing the given server time for interpolation. */
    getInterpolationPair(serverTime: number): [Snapshot, Snapshot] | null;
    getLatest(): Snapshot | null;
    getAtTick(tick: number): Snapshot | undefined;
    clear(): void;
}
/** Linear interpolation between two entity states. */
export declare function interpolateState(a: EntityState, b: EntityState, t: number): EntityState;
/** Client-side prediction: store inputs for reconciliation. */
export interface PredictionInput {
    tick: number;
    inputActions: Record<string, boolean | number>;
    resultPosition: Vec2;
}
export declare class ClientPrediction {
    private pendingInputs;
    addInput(input: PredictionInput): void;
    /** Clear inputs confirmed by server (tick <= serverTick). */
    acknowledge(serverTick: number): void;
    /** Re-apply unconfirmed inputs after server correction. */
    getPendingInputs(): PredictionInput[];
    clear(): void;
}
export interface LobbyRoom {
    id: string;
    name: string;
    hostId: string;
    maxPlayers: number;
    currentPlayers: number;
    isPublic: boolean;
    hasPassword: boolean;
    gameMode: string;
    metadata: Record<string, unknown>;
}
export interface LobbyPlayer {
    peerId: string;
    displayName: string;
    ready: boolean;
    team: number;
    slot: number;
}
export declare class LobbyManager {
    readonly events: EventBus;
    private _room;
    private _players;
    private _localPeerId;
    constructor(localPeerId: string);
    get room(): LobbyRoom | null;
    get players(): LobbyPlayer[];
    get isHost(): boolean;
    get allReady(): boolean;
    /** Create a new room (as host). */
    createRoom(name: string, maxPlayers: number, gameMode: string, isPublic?: boolean): LobbyRoom;
    joinRoom(room: LobbyRoom, displayName: string): void;
    leaveRoom(): void;
    addPlayer(peerId: string, displayName: string): void;
    removePlayer(peerId: string): void;
    setReady(peerId: string, ready: boolean): void;
    setTeam(peerId: string, team: number): void;
    /** Serialize lobby state for broadcasting. */
    toJSON(): {
        room: LobbyRoom;
        players: LobbyPlayer[];
    };
    /** Apply state from host. */
    fromJSON(data: {
        room: LobbyRoom;
        players: LobbyPlayer[];
    }): void;
}
