import { ClientRoleOptions } from '@agora-js/shared';
import { CloudProxyServerMode } from '@agora-js/shared';
import { EncryptionMode } from '@agora-js/shared';
import { Extmap } from '@agora-js/shared';
import { FingerPrint } from '@agora-js/shared';
import type { JsonObject } from '@bufbuild/protobuf';
import type { Message } from '@bufbuild/protobuf';
import { PayloadAttribute } from '@agora-js/shared';
import { RemoteStreamType } from '@agora-js/media';
import { RetryConfiguration } from '@agora-js/shared';
import { RTMConfiguration } from '@agora-js/shared';
import { SDK_CODEC } from '@agora-js/shared';
import { SDK_MODE } from '@agora-js/shared';
import { SDKStore } from '@agora-js/shared';
import { TurnServerConfigWithMode } from '@agora-js/shared';
import { UID } from '@agora-js/shared';
import type { Value } from '@bufbuild/protobuf/wkt';

declare enum AudioExtensionName {
    AUDIO_EXT_AUDIO_LEVEL = 0,
    AUDIO_EXT_ABS_SEND_TIME = 1,
    AUDIO_EXT_TWCC = 2,
    AUDIO_EXT_SDES_MID = 3,
    AUDIO_EXT_SDES_RTP_STREAM_ID = 4,
    AUDIO_EXT_SDS_REPAIRED_RTP_STREAM_ID = 5
}

export declare interface ChooseServerResponse {
    code: number;
    addresses: ServerAddress[];
    server_ts: number;
    uid: number;
    cid: number;
    cert: string;
    detail?: {
        [id: number]: string;
        candidate?: string;
    };
    cname?: string;
    flag?: number;
    opid?: number;
    signalResponse?: SignalResponse;
}

export declare interface DtlsParameters {
    fingerprints: FingerPrint[];
}

declare enum EncodingName {
    UNSPECIFIED = 0,
    VP8 = 1,
    VP9 = 2,
    H264 = 3,
    H265 = 4,
    AV1 = 5,
    G711 = 6,
    G722 = 7,
    OPUS = 8,
    PCMU = 9,
    PCMA = 10,
    CN = 11,
    TELEPHONE_EVENT = 12,
    RTX = 13,
    RED = 14
}

export declare type ExtmapProto = Message<"io.agora.pb.Extmap"> & {
    entry: number;
    extensionName?: Value;
    direction?: string;
    extensionAttributes?: string;
};

declare type Feedback = Message<"io.agora.pb.Feedback"> & {
    enumType?: number;
    stringType?: string;
    parameter?: string;
    additional?: string;
    interval?: string;
};

declare enum FeedbackType {
    UNSPECIFIED = 0,
    GOOG_REMB = 1,
    TRANSPORT_CC = 2,
    CCM = 3,
    NACK = 4,
    RRTR = 5
}

declare type Fmtp = Message<"io.agora.pb.Fmtp"> & {
    enumParameters: {
        [key: number]: Value;
    };
    stringParameters: {
        [key: string]: Value;
    };
};

declare enum FmtpParameter {
    UNSPECIFIED = 0,
    MINPTIME = 1,
    USEINBANDFEC = 2,
    LEVEL_ID = 3,
    PROFILE_ID = 4,
    TIER_FLAG = 5,
    TX_MODE = 6,
    LEVEL_ASYMMETRY_ALLOWED = 7,
    PACKETIZATION_MODE = 8,
    PROFILE_LEVEL_ID = 9,
    LEVEL_IDX = 10,
    PROFILE = 11,
    TIER = 12
}

export declare interface GatewayAddress {
    ip?: string;
    ip6?: string;
    port?: number;
    address: string;
}

export declare interface GatewayClientSpec {
    role?: "host" | "audience";
    codec: SDK_CODEC;
    mode: SDK_MODE;
    clientId: string;
    httpRetryConfig: RetryConfiguration;
    websocketRetryConfig: RetryConfiguration;
    forceWaitGatewayResponse: boolean;
    clientRoleOptions?: ClientRoleOptions;
}

export declare interface GatewayEstablishParams extends RestartICEResponse {
    dtlsParameters: {
        role: "server" | "client" | "auto";
        fingerprints: {
            algorithm: string;
            fingerprint: string;
        }[];
    };
    rtpCapabilities: RTPCapabilitiesBeforeMerge;
    cname: string;
}

export declare interface GatewayInfo {
    gatewayAddrs: GatewayAddress[];
    apGatewayAddress?: GatewayAddress;
    uid: number;
    cid: number;
    cert: string;
    vid?: string;
    uni_lbs_ip?: string;
    res: ChooseServerResponse;
    csIp?: string;
}

export declare interface GatewayJoinResponse {
    attributes: {
        userAttributes: {
            preSubSsrcs?: PreSubSsrc[];
            subscribeAudioFilterTopN?: number;
        } & {
            [key: string]: any;
        };
    };
    rejoin_token: string;
    return_vosip: false;
    uid: UID;
    intUid?: number;
    vid?: number;
    ortc: GatewayEstablishParams;
    rtpCapabilities: RTPCapabilitiesWithDirection;
}

export declare function getEncodingName(encodingName?: EncodingName): string | undefined;

export declare function getEncodingNameEnum(encodingName?: string): EncodingName | undefined;

export declare function getExtmapName(type: "audio" | "video", extmapName?: AudioExtensionName | VideoExtensionName): string | undefined;

export declare function getExtmapNameEnum(type: "audio" | "video", extmapName: string): AudioExtensionName | VideoExtensionName | undefined;

export declare function getFeedbackTypeName(feedbackTypeName?: FeedbackType): string | undefined;

export declare function getFeedbackTypeNameEnum(feedbackTypeName?: string): FeedbackType | undefined;

export declare function getFmtpParameterName(parameterName?: FmtpParameter): string | undefined;

export declare function getFmtpParameterNameEnum(parameterName?: string): FmtpParameter | undefined;

export declare function getGatewayOrtc(localCap: RTPCapabilitiesBeforeMerge, addOrtcPb?: RtpCapBeforeMerge, delOrtcPb?: RtpCapBeforeMerge): RTPCapabilitiesWithDirection;

export declare function getJoinV3Message(store: SDKStore, joinInfo: JoinInfoWithAPResponse, spec: GatewayClientSpec, { key, role, joinGatewayStartTime, hasChangeBGPAddress, isPreallocation, ortc, currentURLIndex, }: {
    key: string;
    role: "host" | "audience";
    joinGatewayStartTime: number;
    hasChangeBGPAddress: boolean;
    isPreallocation: boolean;
    ortc?: JoinV3MessageOrtc;
    currentURLIndex: number;
}): JoinV3;

export declare function getJoinV4Message(store: SDKStore, joinInfo: JoinInfoWithAPResponse | JoinInfo, { mode, codec, joinGatewayStartTime, hasChangeBGPAddress, }: {
    mode: SDK_MODE;
    codec: SDK_CODEC;
    joinGatewayStartTime: number;
    hasChangeBGPAddress: boolean;
}): JoinV4;

export declare function getJoinV4MessageOrtc(ortc: JoinV3MessageOrtc): JoinV4ORTC;

export declare function getSDPEndPointPb(store: SDKStore, info: JoinInfo, areaCode: string | undefined, serviceIds: SERVICE_IDS[], { opid, mode, codec, hasChangeBGPAddress, ortc, }: {
    opid: number;
    mode: SDK_MODE;
    codec: SDK_CODEC;
    hasChangeBGPAddress: boolean;
    ortc: JoinV3MessageOrtc;
}): ArrayBuffer;

export declare interface ICEParameters {
    iceUfrag: string;
    icePwd: string;
}

export declare interface JoinInfo extends Partial<RTMConfiguration> {
    clientId: string;
    appId: string;
    sid: string;
    cname: string;
    turnServer: TurnServerConfigWithMode;
    proxyServer?: string;
    token: string;
    cloudProxyServer: CloudProxyServerMode;
    uid?: number | null;
    stringUid?: string;
    aespassword?: string;
    aessalt?: string;
    aesmode?: EncryptionMode;
    multiIP?: MultiIpOptions;
    optionalInfo?: string;
    appScenario?: string;
    useLocalAccessPoint: boolean;
    apUrl?: string;
    defaultVideoStream?: RemoteStreamType;
    license?: string;
    setLocalAPVersion?: number;
    preload?: boolean;
    apRequestDetail?: string;
    role?: "host" | "audience";
}

export declare interface JoinInfoWithAPResponse extends JoinInfo {
    cid: number;
    uid: number;
    vid?: string;
    apResponse: ChooseServerResponse;
    sdpEndpointLocalIceParameters?: ICEParameters;
    apGatewayAddress?: GatewayAddress;
    gatewayAddrs: GatewayAddress[];
    uni_lbs_ip?: string;
    signalResponse?: SignalResponse;
}

declare interface JoinMessageAttributes {
    userAttributes: JoinMessageUserAttributes;
}

declare interface JoinMessageDetails {
    6?: string;
    cservice_map?: "1" | "2";
}

export declare interface JoinMessageUserAttributes extends Partial<Record<keyof typeof UserAttributeFeature1, boolean>>, Partial<Omit<Required<UserAttributes>, "$typeName" | "$unknown" | "feature2" | "feature1">> {
    [key: string]: any;
}

export declare interface JoinV3 {
    license?: string | undefined;
    p2p_id: number;
    session_id: string;
    app_id: string;
    channel_key: string;
    channel_name: string;
    sdk_version: string;
    browser: string;
    process_id?: string;
    mode: SDK_MODE;
    codec: SDK_CODEC;
    role?: "host" | "audience";
    has_changed_gateway: boolean;
    ap_response: ChooseServerResponse & {
        ticket?: string;
    };
    extend?: any;
    details: JoinMessageDetails;
    features: {
        rejoin: true;
        multi_signaling?: boolean;
    };
    optionalInfo?: string;
    appScenario?: string;
    attributes: JoinMessageAttributes;
    join_ts: number;
    string_uid?: string;
    aes_mode?: EncryptionMode;
    aes_secret?: string;
    aes_encrypt?: boolean;
    aes_salt?: string;
    default_video_stream?: RemoteStreamType;
    ortc: JoinV3MessageOrtc;
}

export declare type JoinV3MessageOrtc = {
    iceParameters: ICEParameters;
    dtlsParameters: DtlsParameters;
    rtpCapabilities: RTPCapabilitiesBeforeMerge;
    version?: string;
};

export declare type JoinV3WithoutAPResponse = Omit<JoinV3, "ap_response">;

export declare type JoinV4 = Omit<SignalRequest, "$typeName" | "attributes"> & {
    attributes: JoinV4UserAttributes;
};

export declare type JoinV4Extmap = Omit<ExtmapProto, "$typeName" | "$unknown" | "extensionName"> & {
    extensionName: number | string;
};

export declare type JoinV4Feedback = Omit<Feedback, "$typeName" | "$unknown">;

export declare type JoinV4Fmtp = Partial<Omit<Fmtp, "$typeName" | "$unknown">>;

export declare type JoinV4ORTC = Omit<ORTC, "$typeName" | "$unknown" | "send" | "recv" | "sendRecv"> & {
    send?: JoinV4RtpCap;
    recv?: JoinV4RtpCap;
    sendRecv?: JoinV4RtpCap;
};

export declare type JoinV4PayloadAttribute = Omit<PayloadAttributeProto, "$typeName" | "$unknown" | "rtpMap" | "fmtp" | "rtcpFeedbacks"> & {
    rtpMap?: JoinV4RtpMap;
    fmtp?: JoinV4Fmtp;
    rtcpFeedbacks: JoinV4Feedback[];
};

export declare type JoinV4RtpCap = Omit<RtpCap, "$typeName" | "$unknown" | "audioCodecs" | "videoCodecs" | "audioExtensions" | "videoExtensions"> & {
    audioCodecs: JoinV4PayloadAttribute[];
    videoCodecs: JoinV4PayloadAttribute[];
    audioExtensions: JoinV4Extmap[];
    videoExtensions: JoinV4Extmap[];
};

export declare type JoinV4RtpMap = Omit<RtpMap, "$typeName" | "$unknown" | "clockRate"> & {
    clockRate: string;
};

export declare type JoinV4UserAttributes = Partial<Omit<UserAttributes, "$typeName" | "$unknown">>;

export declare interface MultiIpOptions {
    gateway_ip: string;
    uni_lbs_ip: string;
}

declare type MultiUnilbsRequest = Message<"io.agora.pb.MultiUnilbsRequest"> & {
    uri: number;
    detail?: JsonObject;
    serviceIds: number[];
};

export declare type MultiUnilbsRequestBody = Omit<MultiUnilbsRequest, "$typeName">;

export declare interface MultiUnilbsResponse {
    detail: {
        502: string;
    };
    enter_ts: number;
    leave_ts: number;
    opid: number;
    response_body: MultiUnilbsResponseBody[];
    wan_ip?: string;
}

export declare interface MultiUnilbsResponseBody {
    buffer: {
        cert: string;
        cid: number;
        cname: string;
        code: number;
        detail: {
            [id: number]: string;
        };
        edges_services: {
            ip: string;
            port: number;
            fingerprint?: string;
            iceUfrag?: string;
            icePwd?: string;
        }[];
        flag: number;
        uid: number;
    };
    uri: 23 | 29;
}

declare type ORTC = Message<"io.agora.pb.ORTC"> & {
    ice: string[];
    dtls: JsonObject[];
    send?: RtpCap;
    recv?: RtpCap;
    sendRecv?: RtpCap;
};

export declare function parseSDPEndPointResponse(info: JoinInfo, ortc: JoinV3MessageOrtc, data: ArrayBuffer): SDPEndPointResponse;

export declare function parseSDPEndPointResponseJson(data: ArrayBuffer): MultiUnilbsResponse;

export declare type PayloadAttributeProto = Message<"io.agora.pb.PayloadAttribute"> & {
    rtpMap?: RtpMap;
    fmtp?: Fmtp;
    rtcpFeedbacks: Feedback[];
    payloadType: number;
};

export declare interface PreSubSsrc {
    a: number;
    a_rtx: number;
    v: number;
    v_rtx: number;
}

export declare interface RestartICEResponse {
    iceParameters: {
        candidates: {
            foundation: string;
            priority: number;
            ip: string;
            port: number;
            protocol: string;
            type: string;
        }[];
        icePwd: string;
        iceUfrag: string;
    };
}

declare type RtpCap = Message<"io.agora.pb.RtpCap"> & {
    audioCodecs: PayloadAttributeProto[];
    videoCodecs: PayloadAttributeProto[];
    audioExtensions: ExtmapProto[];
    videoExtensions: ExtmapProto[];
};

export declare interface RTPCapabilities {
    audioCodecs: PayloadAttribute[];
    videoCodecs: PayloadAttribute[];
    audioExtensions: Extmap[];
    videoExtensions: Extmap[];
}

export declare interface RTPCapabilitiesBeforeMerge extends Partial<RTPCapabilitiesWithDirection> {
    sendrecv?: RTPCapabilities;
}

export declare interface RTPCapabilitiesWithDirection {
    send: RTPCapabilities;
    recv: RTPCapabilities;
}

declare type RtpCapBeforeMerge = Message<"io.agora.pb.RtpCapBeforeMerge"> & {
    send?: RtpCap;
    recv?: RtpCap;
    sendRecv?: RtpCap;
};

declare type RtpMap = Message<"io.agora.pb.RtpMap"> & {
    enumEncodingName?: number;
    stringEncodingName?: string;
    clockRate?: Value;
    encodingParameters?: number;
};

export declare type SdpEndpointRequest = Omit<SdpEndpointRequest_2, "$typeName" | "unilbs" | "signal" | "ortc" | "opid"> & {
    opid: number;
    unilbs: MultiUnilbsRequestBody[];
    signal: JoinV4;
    ortc: JoinV4ORTC;
};

declare type SdpEndpointRequest_2 = Message<"io.agora.pb.SdpEndpointRequest"> & {
    unilbs: MultiUnilbsRequest[];
    uid: number;
    opid: bigint;
    signal?: SignalRequest;
    ortc?: ORTC;
};

export declare interface SDPEndPointResponse extends MultiUnilbsResponse {
    signalResponse?: SignalResponse;
}

export declare interface ServerAddress {
    ip: string;
    port: number;
    fingerprint?: string;
    domain_prefix?: string;
    ticket: string;
    iceUfrag?: string;
    icePwd?: string;
}

export declare enum SERVICE_IDS {
    CHOOSE_SERVER = 11,
    CLOUD_PROXY = 18,
    CLOUD_PROXY_5 = 20,
    CLOUD_PROXY_FALLBACK = 26
}

declare type SignalRequest = Message<"io.agora.pb.SignalRequest"> & {
    license?: string;
    p2pId: number;
    sessionId: string;
    appId: string;
    channelKey: string;
    channelName: string;
    sdkVersion: string;
    browser?: string;
    processId?: Value;
    mode: string;
    codec: string;
    role?: string;
    hasChangedGateway?: boolean;
    extend?: string;
    cserviceMap?: string;
    optionalInfo?: string;
    appScenario?: string;
    attributes?: UserAttributes;
    requestTs: bigint;
    stringUid?: string;
    aesMode?: string;
    aesSecret?: string;
    aesEncrypt?: boolean;
    aesSalt?: string;
    defaultVideoStream?: number;
};

export declare type SignalResponse = Omit<GatewayJoinResponse, "ortc">;

declare enum UserAttributeFeature1 {
    UNSPECIFIED = 0,
    enableEncodedTransform = 1,
    enableAudioMetadata = 2,
    enableAudioPts = 4,
    enableNetworkQualityProbe = 8,
    enablePublishedUserList = 16,
    enablePublishAudioFilter = 32,
    enableUserLicenseCheck = 64,
    enableRTX = 128,
    enableNTPReport = 256,
    enableInstantVideo = 512,
    enableFulllinkAvSync = 1024,
    enableDataStream2 = 2048,
    enableAutFeedback = 4096,
    enableUserAutoRebalanceCheck = 8192,
    enableXR = 16384,
    enableLossbasedBwe = 32768,
    enableAutCC = 65536,
    enableCCFallback = 131072,
    enablePreallocPC = 262144,
    enablePubTWCC = 524288,
    enableSubTWCC = 1048576,
    enablePubRTX = 2097152,
    enableSubRTX = 4194304,
    enableQualityFallback = 8388608,
    senttsUsesAbsSendTime = 16777216,
    enableDualStreamFlag = 33554432,
    disableFEC = 67108864,
    enableVosFallback = 134217728
}

declare type UserAttributes = Message<"io.agora.pb.UserAttributes"> & {
    feature1?: number;
    feature2?: number;
    topnSmoothLevel?: number;
    topnNewSpeakerDelay?: number;
    topnSwitchHoldMs?: number;
    topnAudioGain?: number;
    maxSubscription?: number;
    subscribeAudioFilterTopN?: number;
    rtm2Flag?: number;
    preSubNum?: number;
    preSubUid: Value[];
    enableSubSVC: string[];
    enableSvcExtended: string[];
    audioDuplicate?: number;
    ntpFixedOffset?: number;
    experiments?: JsonObject;
};

declare enum VideoExtensionName {
    VIDEO_EXT_HDR_TOFFSET = 0,
    VIDEO_EXT_ABS_SEND_TIME = 1,
    VIDEO_EXT_ORIENTATION = 2,
    VIDEO_EXT_TWCC = 3,
    VIDEO_EXT_PLAYOUT_DELAY = 4,
    VIDEO_EXT_CONTENT_TYPE = 5,
    VIDEO_EXT_VIDEO_TIMING = 6,
    VIDEO_EXT_COLOR_SPACE = 7,
    VIDEO_EXT_SDES_MID = 8,
    VIDEO_EXT_SDES_RTP_STREAM_ID = 9,
    VIDEO_EXT_SDED_REPAIRED_RTP_STREAM_ID = 10
}

export { }
