import Stutter from '../../util/Stutter';
import Player from '../../player/Player';
import { UserId } from '../../type/value';
import ReportCollector from '../../util/ReportCollector';
import { Collection, ReportThreshold } from '../../type/type';
import { TencentStream, VloudStream } from '../../type/stream';
import { TencentClient, BloudClient } from '../../type/client';
import { LocalStreamStats, RemoteStreamStats, ReportStats } from '../../type/stats';
import { StreamPlayOption, Stream as StreamInterface } from '../../type/BRTCStream';
export default abstract class Stream implements StreamInterface {
    /**
     *
     * @internal
     */
    static readonly STREAM_TYPE_LOCAL = 0;
    /**
     *
     * @internal
     */
    static readonly STREAM_TYPE_REMOTE = 1;
    type: number;
    protected uid: UserId | undefined;
    protected sid: string;
    protected stream: VloudStream | TencentStream | undefined | null;
    protected subStream: VloudStream[] | TencentStream[];
    protected webrtcType: number;
    protected playing: boolean | undefined;
    protected player: Player | undefined | null;
    protected audioDeviceId: string | undefined;
    protected audioVolume: number | undefined;
    protected client: BloudClient | TencentClient | undefined | null;
    protected collection: Collection | null | undefined;
    private emitter;
    private debounceReplay;
    private debounceSetVolumeMeter;
    /**
     * audioTrack 监听事件
     */
    private audioTrackEventHandler;
    /**
     * videoTrack 监听事件
     */
    private videoTrackEventHandler;
    protected reportCollector: ReportCollector | null;
    protected stutter: Stutter | undefined | null;
    /**
     * 创建流实例
     *
     * @param type 流类型
     * @param uid 用户 id
     * @param unumber 用户 number
     * @param webrtcType webrtc 底层类型
     * @param stream 底层流对象
     * @returns Stream
     */
    constructor(type: number, sid?: string, uid?: UserId, webrtcType?: number, stream?: any, subStream?: any);
    /**
     * 判断流实例是否相同
     * @internal
     * @returns
     */
    isStream(stream: VloudStream | TencentStream): boolean;
    /**
    * 判断是否是本地流
    *
    * @returns
    */
    isLocalStream(): boolean;
    /**
     * 是否是屏幕分享流
     *
     * @returns
     */
    isScreenStream(): boolean;
    /**
     * 流是否正在播放
     *
     * @returns
     */
    isPlaying(): boolean;
    /**
     * 获取媒体底层
     *
     * @internal
     * @returns
     */
    getWebRTCType(): number;
    /**
     * 获取 userId
     *
     * @returns
     */
    getUserId(): UserId;
    /**
     * 设置 userId
     *
     * @internal
     * @param uid 用户 id
     */
    setUserId(uid: UserId): void;
    /**
     * 获取 stream id
     *
     * @returns
     */
    getStreamId(): string;
    /**
     * 设置 streamId
     *
     * @internal
     * @param uid 用户 id
     */
    setStreamId(sid: string): void;
    /**
     * 获取底层流实例
     *
     * @internal
     * @returns
     */
    getStream(): VloudStream | TencentStream;
    /**
     * 设置底层流实例
     *
     * @internal
     * @param webrtcType 底层类型
     * @param stream 底层流实例
     */
    setStream(webrtcType: number, stream: any): void;
    /**
     * 获取底层 client 实例
     *
     * @internal
     * @param client
     */
    getClient(): BloudClient | TencentClient;
    /**
     * 设置底层 client 实例
     *
     * @internal
     * @param client
     */
    setClient(client: BloudClient | TencentClient | null): void;
    /**
     * 设置 collection 实例
     *
     * @internal
     * @param server
     */
    setCollection(collection: Collection | null): void;
    /**
     * 获取 collection 实例
     *
     * @internal
     * @param client
     */
    getCollection(): Collection | undefined;
    /**
     * 是否有视频
     *
     * @returns
     */
    hasVideo(): boolean;
    /**
     * 是否有音频
     *
     * @returns
     */
    hasAudio(): boolean;
    /**
     * 获取流视频是否挂起
     *
     * @returns
     */
    getVideoOn(): boolean;
    /**
     * 获取流音频是否挂起
     *
     * @returns
     */
    getAudioOn(): boolean;
    /**
     * 音频轨道
     */
    get audioTrack(): MediaStreamTrack | undefined;
    /**
     * 视频轨道
     */
    get videoTrack(): MediaStreamTrack | undefined;
    /**
     * 获取音频轨道
     *
     * @returns
     */
    getAudioTrack(): MediaStreamTrack | undefined;
    /**
     * 获取视频轨道
     *
     * @returns
     */
    getVideoTrack(): MediaStreamTrack | undefined;
    /**
     * 获取 MediaStream 实例
     *
     * @internal
     * @returns
     */
    getMediaStream(): MediaStream | undefined;
    /**
     * 禁用视频轨道
     * 对于本地流，调用该方法会停止发送视频，远端会触发 Client.on('mute-video') 事件
     * 如果视频是从摄像头采集，此时摄像头灯仍然是亮着的。若想完全禁用视频轨道(即关闭摄像头)
     * 可以使用 removeTrack() 删除视频轨道然后调用 MediaStreamTrack.stop() 关闭视频轨道（关闭摄像头）
     * 对于远端流，调用该方法会停止播放视频，但是仍然接收视频数据。
     *
     * @returns 是否成功
     */
    muteVideo(): Promise<boolean>;
    /**
     * 启用视频轨道
     * 对于本地流，调用该方法会触发远端 Client.on('unmute-video') 事件。
     * 视频轨道默认是开启的，若你调用 muteVideo() 后可用该方法重新启用视频。
     *
     * @returns 是否成功
     */
    unmuteVideo(): Promise<boolean>;
    /**
     * 禁用音频轨道
     * 对于本地流，调用该方法会停止发送音频，远端会触发 Client.on('mute-audio') 事件。
     * 对于远端流，调用该方法会停止播放音频，但是仍然接收音频数据。
     *
     * @returns 是否成功
     */
    muteAudio(): Promise<boolean>;
    /**
     * 启用音频轨道
     * 对于本地流，调用该方法会触发远端 Client.on('unmute-audio') 事件。
     * 音频轨道默认是开启的，若你调用 muteAudio() 后可用该方法重新启用音频。
     *
     * @returns 是否成功
     */
    unmuteAudio(): Promise<boolean>;
    /**
     * 播放流
     *
     * @param videoId 挂载 dom
     * @param options 播放选项
     *
     * @return
     */
    play(videoId: string | HTMLDivElement, options?: StreamPlayOption): Promise<any>;
    /**
     * 重新播放流
     *
     * @return
     */
    replay(): Promise<void>;
    /**
     * 恢复播放音视频
     * 在某些版本浏览器上移动传入 play() 的 div 容器可能会导致音视频播放器进入 ‘PAUSED’ 状态，此时 需要调用该接口恢复播放。
     * 由于浏览器自动播放策略的限制，在 play() 返回 PLAY_NOT_ALLOWED 错误后需要引导用户通过手势 调用该接口恢复播放
     *
     * @returns
     */
    resume(): Promise<any>;
    /**
     * 停止播放流
     *
     * @returns
     */
    stop(): void;
    /**
     * 关闭流
     */
    /**
     * 销毁音视频流
     *
     */
    destroy(): void;
    /**
     * 获取流的麦克风音量
     *
     * @returns
     */
    getAudioLevel(): number;
    /**
     * 提交事件
     *
     * @param type 事件类型
     * @param data 事件数据
     * @returns
     */
    fire(type: string, data?: any): void;
    /**
     * 监听事件
     *
     * @param type 事件类型
     * @param fn 事件回调
     * @returns 实例本身 {@link Stream}
     */
    on(type: string, fn: Function): this;
    /**
     * 监听一次事件，执行一次之后自动取消监听
     *
     * @param type 事件类型
     * @param fn 事件回调
     * @returns 实例本身 {@link Stream}
     */
    one(type: string, fn: Function): this;
    /**
     * 取消事件监听
     * 只传 type 取消此事件的所有监听
     * 不传任何参数取消所有事件的监听
     *
     * @param type 事件类型
     * @param fn 事件回调
     * @return 实例本身 {@link Stream}
     */
    off(type?: string, fn?: Function): this;
    /**
     * 设置 VolumeMeter 模块
     *
     * @internal
     * @returns
     */
    setVolumeMeter(): void;
    /**
     * 获取当前播放的扬声器设备 id
     *
     * @returns
     */
    getAudioDeviceId(): string;
    /**
     * 获取当前播放音量
     *
     * @returns
     */
    getAudioVolume(): number;
    setAudioVolume(volume: number): void;
    /**
     * 截取当前流的一帧视频数据（base64 png），该方法需要在 play() 后调用，并且 Stream 中有视频流才有效
     *
     * @returns
     */
    getVideoFrame(): string;
    protected addEvents(): void;
    protected removeEvents(): void;
    protected addVideoTrackEvents(): void;
    protected removeVideoTrackEvents(): void;
    protected addAudioTrackEvents(): void;
    protected removeAudioTrackEvents(): void;
    protected removeHandleEvents(): void;
    protected handleEvents(): void;
    /**
     * 上报事件
     * @param type
     * @param error
     * @param sendTs
     * @param receiveTs
     * @param options
     */
    private reportAction;
    /**
     * 获取流的传输信息
     *
     * @returns
     */
    abstract getStats(): Promise<LocalStreamStats | RemoteStreamStats>;
    /**
     * 获取流的上报信息
     * @internal
     * @returns
     */
    abstract getReportStats(reportThreshold: ReportThreshold): Promise<ReportStats>;
    /**
     * 上报的其他信息
     *
     * @internal
     */
    abstract getExtraReport(): Object | undefined;
}
