import { Socket } from 'socket.io-client';

type Callback = (...args: any[]) => void;
type EventMap = Map<string, Set<Callback>>;
declare class CustomEventTarget {
    target: EventTarget;
    eventMap: EventMap;
    constructor(target?: EventTarget);
    on(eventName: string, callback: (...args: any[]) => void): void;
    off(eventName: string, callback?: (...args: any[]) => void): void;
    offAll(): void;
    close(): void;
}

declare class WebRTC {
    configuration: RTCConfiguration;
    peerConnection: RTCPeerConnection;
    dataChannel: RTCDataChannel;
    peerConnectionEventTaget: CustomEventTarget;
    dataChannelEventTarget: CustomEventTarget;
    constructor(configuration: RTCConfiguration);
    init(): void;
    createPeerConnection(): void;
    createDataChannel(label: string, option?: RTCDataChannelInit): RTCDataChannel;
    get signalingState(): RTCSignalingState;
    addTrack(track: MediaStreamTrack | MediaStreamTrack[], stream: MediaStream): RTCRtpSender[];
    removeTrack(sender?: RTCRtpSender | RTCRtpSender[]): void;
    addTransceiver(track: MediaStreamTrack | MediaStreamTrack[], stream: MediaStream): RTCRtpTransceiver[];
    createAnswer(options?: RTCAnswerOptions): Promise<RTCSessionDescriptionInit>;
    createOffer(options?: RTCAnswerOptions): Promise<RTCSessionDescriptionInit>;
    close(): void;
}

declare enum DatachannelReadyState {
    CONNECTING = "connecting",
    OPEN = "open",
    CLOSING = "closing",
    CLOSED = "closed"
}
declare enum MittEventName {
    CONNECTOR_INFO_LIST_CHANGE = "connectorInfoListChange",
    DISPLAY_STREAM_CHANGE = "displayStreamChange",
    LOCAL_STREAM_CHANGE = "localStreamChange",
    MESSAGE = "message",
    ERROR = "error"
}

type Message = {
    id: string;
    isSelf: boolean;
    username: string;
    HHmmss: string;
    type: 'file' | 'text';
    text?: string;
    fileInfo?: {
        name: string;
        size: string;
        type: string;
        url: string;
        FQ: number;
        file: File;
        chunks: string[];
    };
};
type FileMessageData = {
    id: string;
    chunk: string;
    index: number;
};
type Datachannel = {
    readyState: DatachannelReadyState;
    bufferedAmount: number;
    bufferedAmountLowThreshold: number;
    send(data: string): void;
    close(): void;
};
type ConnectorInfoList = Pick<ConnectorInfo, 'streamType' | 'connectorId' | 'remoteStream'>[];
type MittEventType = {
    connectorInfoListChange: ConnectorInfoList;
    displayStreamChange: MediaStream;
    localStreamChange: MediaStream;
    message: Message;
    error: ErrorMessage;
};
type ErrorMessage = {
    type: string;
    message: string;
};
type MessageDataType = 'offer' | 'answer' | 'icecandidate' | 'getOffer' | 'leave' | 'close' | 'chat' | 'file';
type ChannelMessageData = {
    type: MessageDataType;
    data?: {
        [x: string]: any;
    };
};
type ReconnectMessageData = {
    type: MessageDataType;
    connectorId: string;
    memberId: string;
    data?: {
        [x: string]: any;
    };
};
type MemberInfo = {
    memberId: string;
};
type OfferMessageData = {
    remoteConnectorId: string;
    memberId: string;
    offer: RTCSessionDescriptionInit;
    streamType?: StreamType;
};
type StreamType = 'user' | 'display' | 'remoteDisplay';
type Type = 'offer' | 'answer';
type Kind = 'audio' | 'video';
type ControlType = 'add' | 'remove';
type SendGetOfferMessageData = {
    kind?: Kind;
    type?: ControlType;
};
type ConnectorInfo = {
    type: Type;
    streamType: StreamType;
    webrtc: WebRTC;
    connectorId: string;
    memberId: string;
    remoteConnectorId?: string;
    remoteStream?: MediaStream;
    channel?: RTCDataChannel;
    senders?: RTCRtpSender[];
    receivers?: RTCRtpReceiver[];
    transceivers?: RTCRtpTransceiver[];
    messageList: Record<string, Message>;
    chunks: Record<string, [string, number][]>;
};
type ConnectorInfoMap = Map<string, ConnectorInfo>;
type Options$1 = {
    configuration: RTCConfiguration;
    constraints: MediaStreamConstraints;
    socketConfig: {
        host: string;
        port?: number | string;
    };
};
type UserInfo = {
    id: string;
    username?: string;
    roomname?: string;
};

type Options = {
    host: string;
    port?: number | string;
};
type ConnectFunc = (...args: any[]) => void;

declare class SocketClient {
    readonly socket: Socket;
    private connect;
    constructor(options: Options);
    sendMessage(messageName: string, message?: any): void;
    onMessage(messageName: string, callback: <T>(message: T) => void): void;
    offMessage(messageName: string, callback: <T>(message: T) => void): void;
    onConnect(callback: ConnectFunc): void;
    sendTextMessage(message: string): void;
    sendImageMessage(message: File | Blob | string): void;
    sendFileMessage(message: File | Blob | string): void;
    bind(): void;
    close(): void;
}

declare class MediaDevices {
    constraints: MediaStreamConstraints;
    localStream: MediaStream;
    displayStream: MediaStream;
    locaStreamEventTaget: CustomEventTarget;
    displayStreamEventTarget: CustomEventTarget;
    locaStreamTrackEventTargets: CustomEventTarget[];
    displayStreamTrackEventTargets: CustomEventTarget[];
    constructor(constraints: MediaStreamConstraints);
    private getUserStream;
    getUserMedia(): Promise<MediaStream>;
    getUserVideoMedia(): Promise<MediaStream>;
    getUserAudioMedia(): Promise<MediaStream>;
    getDisplayMedia(): Promise<MediaStream>;
    static enumerateDevices(): Promise<MediaDeviceInfo[]>;
    static getSupportedConstraints(): MediaTrackSupportedConstraints;
    getUserMediaStreamTracks(): Promise<MediaStreamTrack[]>;
    getUserAudioTracks(): Promise<MediaStreamTrack[]>;
    getUserVideoTracks(): Promise<MediaStreamTrack[]>;
    getDisplayMediaStreamTracks(): Promise<MediaStreamTrack[]>;
    getDisplayAudioTracks(): Promise<MediaStreamTrack[]>;
    getDisplayVideoTracks(): Promise<MediaStreamTrack[]>;
    addTrack(track: MediaStreamTrack | MediaStreamTrack[], stream: MediaStream): void;
    removeTrack(track: MediaStreamTrack | MediaStreamTrack[], stream: MediaStream): void;
    startUserMediaStreamTrack(id?: string): Promise<void>;
    stopUserMediaStreamTrack(id?: string): Promise<void>;
    startDisplayMediaStreamTrack(id?: string): Promise<void>;
    stopDisplayMediaStreamTrack(id?: string): Promise<void>;
    closeUserMediaStream(): void;
    closeDisplayMediaStream(): void;
    close(): void;
}

declare class RTCClient extends SocketClient {
    configuration: RTCConfiguration;
    streamConstraints: MediaStreamConstraints;
    mediaDevices: MediaDevices;
    userInfo: UserInfo;
    readonly messageQueueSize: number;
    private emitter;
    private connectorInfoMap;
    private audioState;
    private videoState;
    constructor(options: Options$1);
    /**
     * 共享屏幕状态
     */
    private _displayState;
    get displayState(): boolean;
    private init;
    /**
     * 创建客户端之间的连接
     * @param type
     * @param streamType
     * @returns
     */
    private createConnector;
    private createDataChannel;
    on<K extends keyof MittEventType, Args extends MittEventType[K]>(type: K, listener: (args: Args) => void): void;
    off(type: keyof MittEventType, listener?: (...args: any[]) => void): void;
    getDevicesInfoList(): Promise<MediaDeviceInfo[]>;
    getVideoDeviceInfo(): Promise<MediaDeviceInfo>;
    getAudioDeviceInfo(): Promise<MediaDeviceInfo>;
    private bindSocketEvent;
    private bindPeerConnectionEvent;
    private bindDataChannelEvent;
    private bindDisplayMediaStreamTrackEvent;
    /**
     * 添加本地媒体流
     * @param connectorInfo
     */
    private addLocalStream;
    /**
     * 添加共享屏幕媒体流
     * @param connectorInfo
     */
    private addDisplayStream;
    /**
     * 屏幕共享媒体流的视频轨道启用状态变化处理事件
     * @param event
     */
    private displayStreamTrackEnded;
    /**
     * 创建客户端之间的共享屏幕的连接
     * @param memberInfo
     */
    private createDisplayConnector;
    /**
     * 暴露共享屏幕接口
     */
    shareDisplayMedia(): Promise<MediaStream>;
    /**
     * 暴露取消屏幕共享接口
     */
    cancelShareDisplayMedia(): void;
    private closeDisplayConnector;
    /**
     * 加入房间状态
     */
    private _state;
    get state(): string;
    join(data: {
        username: string;
        roomname: string;
    }): void;
    leave(): void;
    /**
     * socket getOffer 消息处理事件，远程客户端发起请求，信令服务器通知
     * @param memberInfo
     */
    private getOfferMessage;
    /**
     * socket offer 消息处理事件，远程客户端发起请求，信令服务器通知
     * @param memberInfo
     */
    private offerMessage;
    /**
     * socket answer 消息处理事件，远程客户端发起请求，信令服务器通知
     * @param memberInfo
     */
    private answerMessage;
    /**
     * 接收信息通道
     * @param connectorInfo
     * @param event
     */
    private ondatachannel;
    /**
     * dataChannel信息通道消息处理事件
     * @param connectorInfo
     * @param event
     */
    private dataChannelMessage;
    /**
     * RTCDataChannel close事件 connector关闭通知事件
     * @param memberInfo
     */
    private closeMessage;
    /**
     * socket leave事件 成员退出通知事件
     * @param memberInfo
     */
    private leaveMessage;
    /**
     * RTCPeerConnection绑定事件 对等方有新的媒体轨道加入时通知
     * @param connectorInfo
     * @param event
     */
    private ontrack;
    private onremovetrack;
    /**
     * RTCPeerConnection绑定事件 第一次offer SDP、answer SDP交换完成连接成功后执行
     * @param connectorInfo
     * @param event
     */
    private onicecandidate;
    /**
     * socket 事件，远程客户端发起，信令服务器通知，ICE Candidate 交换
     * @param data
     * @returns
     */
    private icecandidateMessage;
    /**
     * 房间内断开重连
     * @returns
     */
    private reconnect;
    private reconnectMessage;
    private reconnectWork;
    private errorMessage;
    private sendIcecandidateMessage;
    private sendOfferMessage;
    private sendAnswerMessage;
    private channelSend;
    private sendJoinMessage;
    private sendleaveMessage;
    private sendCloseMessage;
    private sendReconnectMessage;
    channelSendMesage(data: Message): void;
    /**
     * 切换设备或设备状态后刷新连接，刷新依赖于RTCDataChannel信息通道
     * @param connectorInfo
     */
    private restartConnector;
    private addTrack;
    private removeTrack;
    /**
     * 切换设备媒体轨道
     * @param deviceId
     * @param kind
     */
    replaceTrack(deviceId: string, kind: Kind): Promise<void>;
    replaceVideoTrack(deviceId: string): Promise<void>;
    replaceAudioTrack(deviceId: string): Promise<void>;
    /**
     * 切换设备状态，本质还是改变媒体轨道
     * @param state
     * @param kind
     */
    deviceSwitch(state: boolean, kind: Kind): Promise<void>;
    disableAudio(): Promise<void>;
    enableAudio(): Promise<void>;
    disableVideo(): Promise<void>;
    enableVideo(): Promise<void>;
    getLocalStream(): Promise<MediaStream>;
    getDisplayStream(): Promise<MediaStream>;
    /**
     * 防抖通知
     */
    private [MittEventName.CONNECTOR_INFO_LIST_CHANGE];
    private closeConnectorById;
    private closeAllConnector;
    /**
     * 写这个函数的目的是解决当退出房间时直接emitter.all.clear()清除事件
     * 会导致MittEventName.CONNECTOR_INFO_LIST_CHANGE无法通知外界连接成员列表已改变
     */
    private clearEmitter;
    close(): void;
}

export { type ChannelMessageData, type ConnectorInfo, type ConnectorInfoList, type ConnectorInfoMap, type ControlType, type Datachannel, type ErrorMessage, type FileMessageData, type Kind, type MemberInfo, type Message, type MessageDataType, type MittEventType, type OfferMessageData, type Options$1 as Options, type ReconnectMessageData, type SendGetOfferMessageData, type StreamType, type Type, type UserInfo, RTCClient as default };
