import { ServerMessage } from './proto.js';
import axios from 'axios';
import '@bufbuild/protobuf/wire';

/**
 * Describes peer status
 * @export
 * @interface Peer
 */
interface Peer$1 {
    /**
     * Assigned peer id
     * @type {string}
     * @memberof Peer
     */
    'id': string;
    /**
     * Custom metadata set by the peer
     * @type {any}
     * @memberof Peer
     */
    'metadata': any | null;
    /**
     *
     * @type {PeerStatus}
     * @memberof Peer
     */
    'status': PeerStatus;
    /**
     * List of all peer\'s tracks
     * @type {Array<Track>}
     * @memberof Peer
     */
    'tracks': Array<Track>;
    /**
     * Peer type
     * @type {string}
     * @memberof Peer
     */
    'type': string;
}
/**
 * @type PeerOptions
 * Peer-specific options
 * @export
 */
type PeerOptions = PeerOptionsWebRTC;
/**
 * Options specific to the WebRTC peer
 * @export
 * @interface PeerOptionsWebRTC
 */
interface PeerOptionsWebRTC {
    /**
     * Enables the peer to use simulcast
     * @type {boolean}
     * @memberof PeerOptionsWebRTC
     */
    'enableSimulcast'?: boolean;
    /**
     * Custom peer metadata
     * @type {{ [key: string]: any; }}
     * @memberof PeerOptionsWebRTC
     */
    'metadata'?: {
        [key: string]: any;
    };
}
/**
 * Informs about the peer status
 * @export
 * @enum {string}
 */
declare const PeerStatus: {
    readonly Connected: "connected";
    readonly Disconnected: "disconnected";
};
type PeerStatus = typeof PeerStatus[keyof typeof PeerStatus];
/**
 * Room configuration
 * @export
 * @interface RoomConfig
 */
interface RoomConfig {
    /**
     * Maximum amount of peers allowed into the room
     * @type {number}
     * @memberof RoomConfig
     */
    'maxPeers'?: number | null;
    /**
     * Duration (in seconds) after which the peer will be removed if it is disconnected. If not provided, this feature is disabled.
     * @type {number}
     * @memberof RoomConfig
     */
    'peerDisconnectedTimeout'?: number | null;
    /**
     * Duration (in seconds) after which the room will be removed if no peers are connected. If not provided, this feature is disabled.
     * @type {number}
     * @memberof RoomConfig
     */
    'peerlessPurgeTimeout'?: number | null;
    /**
     * The use-case of the room. If not provided, this defaults to full_feature.
     * @type {string}
     * @memberof RoomConfig
     */
    'roomType'?: RoomConfigRoomTypeEnum;
    /**
     * Enforces video codec for each peer in the room
     * @type {string}
     * @memberof RoomConfig
     */
    'videoCodec'?: RoomConfigVideoCodecEnum | null;
    /**
     * URL where Fishjam notifications will be sent
     * @type {string}
     * @memberof RoomConfig
     */
    'webhookUrl'?: string | null;
}
declare const RoomConfigRoomTypeEnum: {
    readonly FullFeature: "full_feature";
    readonly AudioOnly: "audio_only";
    readonly Broadcaster: "broadcaster";
};
type RoomConfigRoomTypeEnum = typeof RoomConfigRoomTypeEnum[keyof typeof RoomConfigRoomTypeEnum];
declare const RoomConfigVideoCodecEnum: {
    readonly H264: "h264";
    readonly Vp8: "vp8";
};
type RoomConfigVideoCodecEnum = typeof RoomConfigVideoCodecEnum[keyof typeof RoomConfigVideoCodecEnum];
/**
 * Describes media track of a Peer or Component
 * @export
 * @interface Track
 */
interface Track {
    /**
     *
     * @type {string}
     * @memberof Track
     */
    'id'?: string;
    /**
     *
     * @type {any}
     * @memberof Track
     */
    'metadata'?: any | null;
    /**
     *
     * @type {string}
     * @memberof Track
     */
    'type'?: TrackTypeEnum;
}
declare const TrackTypeEnum: {
    readonly Audio: "audio";
    readonly Video: "video";
};
type TrackTypeEnum = typeof TrackTypeEnum[keyof typeof TrackTypeEnum];
/**
 * Token for authorizing broadcaster viewer connection
 * @export
 * @interface ViewerToken
 */
interface ViewerToken {
    /**
     *
     * @type {string}
     * @memberof ViewerToken
     */
    'token'?: string;
}

type EventMap = {
  [key: string]: (...args: any[]) => void
}

/**
 * Type-safe event emitter.
 *
 * Use it like this:
 *
 * ```typescript
 * type MyEvents = {
 *   error: (error: Error) => void;
 *   message: (from: string, content: string) => void;
 * }
 *
 * const myEmitter = new EventEmitter() as TypedEmitter<MyEvents>;
 *
 * myEmitter.emit("error", "x")  // <- Will catch this type error;
 * ```
 */
interface TypedEventEmitter<Events extends EventMap> {
  addListener<E extends keyof Events> (event: E, listener: Events[E]): this
  on<E extends keyof Events> (event: E, listener: Events[E]): this
  once<E extends keyof Events> (event: E, listener: Events[E]): this
  prependListener<E extends keyof Events> (event: E, listener: Events[E]): this
  prependOnceListener<E extends keyof Events> (event: E, listener: Events[E]): this

  off<E extends keyof Events>(event: E, listener: Events[E]): this
  removeAllListeners<E extends keyof Events> (event?: E): this
  removeListener<E extends keyof Events> (event: E, listener: Events[E]): this

  emit<E extends keyof Events> (event: E, ...args: Parameters<Events[E]>): boolean
  // The sloppy `eventNames()` return type is to mitigate type incompatibilities - see #5
  eventNames (): (keyof Events | string | symbol)[]
  rawListeners<E extends keyof Events> (event: E): Events[E][]
  listeners<E extends keyof Events> (event: E): Events[E][]
  listenerCount<E extends keyof Events> (event: E): number

  getMaxListeners (): number
  setMaxListeners (maxListeners: number): this
}

declare const brand: unique symbol;
/**
 * Branded type helper
 */
type Brand<T, TBrand extends string> = T & {
    [brand]: TBrand;
};
/**
 * ID of the Room.
 * Room can be created with {@link FishjamClient.createRoom}.
 */
type RoomId = Brand<string, 'RoomId'>;
/**
 * ID of Peer. Peer is associated with Room and can be created with {@link FishjamClient.createPeer}.
 */
type PeerId = Brand<string, 'PeerId'>;
type Peer = Omit<Peer$1, 'id'> & {
    id: PeerId;
};
type Room = {
    id: RoomId;
    peers: Peer[];
    config: RoomOptions;
};
type FishjamConfig = {
    fishjamUrl: string;
    managementToken: string;
};
type RoomOptions = {
    /**
     * Maximum amount of peers allowed into the room
     * @type {number}
     */
    maxPeers?: number | null;
    /**
     * Duration (in seconds) after which the peer will be removed if it is disconnected. If not provided, this feature is disabled.
     * @type {number}
     */
    peerDisconnectedTimeout?: number | null;
    /**
     * Duration (in seconds) after which the room will be removed if no peers are connected. If not provided, this feature is disabled.
     * @type {number}
     */
    peerlessPurgeTimeout?: number | null;
    /**
     * The use-case of the room. If not provided, this defaults to full_feature.
     * @type {string}
     */
    roomType?: RoomConfigRoomTypeEnum | 'livestream';
    /**
     * Enforces video codec for each peer in the room
     * @type {string}
     */
    videoCodec?: RoomConfigVideoCodecEnum | null;
    /**
     * URL where Fishjam notifications will be sent
     * @type {string}
     */
    webhookUrl?: string | null;
};

type ExpectedEvents = 'roomCreated' | 'roomDeleted' | 'roomCrashed' | 'peerAdded' | 'peerDeleted' | 'peerConnected' | 'peerDisconnected' | 'peerMetadataUpdated' | 'peerCrashed' | 'trackAdded' | 'trackRemoved' | 'trackMetadataUpdated';
type ErrorEventHandler = (msg: Error) => void;
type CloseEventHandler = (code: number, reason: string) => void;
type NotificationEvents = Record<ExpectedEvents, (message: ServerMessage) => void>;
declare const FishjamWSNotifier_base: new () => TypedEventEmitter<NotificationEvents>;
/**
 * Notifier object that can be used to get notified about various events related to the Fishjam App.
 * @category Client
 */
declare class FishjamWSNotifier extends FishjamWSNotifier_base {
    private readonly client;
    constructor(config: FishjamConfig, onError: ErrorEventHandler, onClose: CloseEventHandler, onConnectionFailed: ErrorEventHandler);
    private dispatchNotification;
    private setupConnection;
    private isExpectedEvent;
}

/**
 * Client class that allows to manage Rooms and Peers for a Fishjam App.
 * It requires the Fishjam URL and management token that can be retrieved from the Fishjam Dashboard.
 * @category Client
 */
declare class FishjamClient {
    private readonly roomApi;
    private readonly viewerApi;
    /**
     * Create new instance of Fishjam Client.
     *
     * Example usage:
     * ```
     * const fishjamClient = new FishjamClient({
     *   fishjamUrl: fastify.config.FISHJAM_URL,
     *   managementToken: fastify.config.FISHJAM_MANAGEMENT_TOKEN,
     * });
     * ```
     */
    constructor(config: FishjamConfig);
    /**
     * Create a new room. All peers connected to the same room will be able to send/receive streams to each other.
     */
    createRoom(config?: RoomOptions): Promise<Room>;
    /**
     * Delete an existing room. All peers connected to this room will be disconnected and removed.
     */
    deleteRoom(roomId: RoomId): Promise<void>;
    /**
     * Get a list of all existing rooms.
     */
    getAllRooms(): Promise<Room[]>;
    /**
     * Create a new peer assigned to a room.
     */
    createPeer(roomId: RoomId, options?: PeerOptions): Promise<{
        peer: Peer;
        peerToken: string;
    }>;
    /**
     * Get details about a given room.
     */
    getRoom(roomId: RoomId): Promise<Room>;
    /**
     * Delete a peer - this will also disconnect the peer from the room.
     */
    deletePeer(roomId: RoomId, peerId: PeerId): Promise<void>;
    /**
     * Refresh the peer token for an already existing peer.
     * If an already created peer has not been connected to the room for more than 24 hours, the token will become invalid. This method can be used to generate a new peer token for the existing peer.
     * @returns refreshed peer token
     */
    refreshPeerToken(roomId: RoomId, peerId: PeerId): Promise<string>;
    /**
     * Creates a livestream viewer token for the given room.
     * @returns a livestream viewer token
     */
    createLivestreamViewerToken(roomId: RoomId): Promise<ViewerToken>;
}

declare class FishjamBaseException extends Error {
    statusCode: number;
    axiosCode?: string;
    details?: string;
    constructor(error: axios.AxiosError<Record<string, string>>);
}
declare class BadRequestException extends FishjamBaseException {
}
declare class UnauthorizedException extends FishjamBaseException {
}
declare class ForbiddenException extends FishjamBaseException {
}
declare class RoomNotFoundException extends FishjamBaseException {
}
declare class FishjamNotFoundException extends FishjamBaseException {
}
declare class PeerNotFoundException extends FishjamBaseException {
}
declare class ServiceUnavailableException extends FishjamBaseException {
}
declare class UnknownException extends FishjamBaseException {
}

export { BadRequestException, type Brand, type CloseEventHandler, type ErrorEventHandler, type ExpectedEvents, FishjamBaseException, FishjamClient, type FishjamConfig, FishjamNotFoundException, FishjamWSNotifier, ForbiddenException, type NotificationEvents, type Peer, type PeerId, PeerNotFoundException, type PeerOptions, PeerStatus, type Room, type RoomConfig, RoomConfigRoomTypeEnum, RoomConfigVideoCodecEnum, type RoomId, RoomNotFoundException, type RoomOptions, ServiceUnavailableException, UnauthorizedException, UnknownException, type ViewerToken };
