import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
import TXAudioEffectManager from './tx_audio_effect_manager';
import TXDeviceManager from './tx_device_manager';
import TXBeautyManager from './tx_beauty_manager';

import { TRTCCloudListener } from './trtc_cloud_listener';
import {
  TRTCParams,
  TRTCCloudDef,
  TXVoiceChangerType,
  TXVoiceReverbType,
  TXSystemVolumeType,
  TRTCRecordType,
} from './trtc_cloud_def';

import type {
  TRTCVideoEncParam,
  TRTCSwitchRoomConfig,
  AudioMusicParam,
  TRTCAudioRecordingParams,
  TRTCPublishCDNParam,
  TRTCNetworkQosParam,
  TRTCTranscodingConfig,
  TRTCRenderParams,
  TRTCSpeedTestParams,
  TRTCLocalRecordingParams,
} from './trtc_cloud_def';
import TXVideoView from './tx_video_view';
const { TRTCReactNativeSdk } = NativeModules;
const TRTCEventEmitter = new NativeEventEmitter(TRTCReactNativeSdk);

export default class TRTCCloud {
  static _trtcCloud: TRTCCloud | undefined;
  private _listeners: Map<any, any>;
  constructor() {
    this._listeners = new Map();
  }
  /**
  Create TRTCCloud instance (singleton mode)
  */
  static sharedInstance() {
    if (!this._trtcCloud) {
      this._trtcCloud = new TRTCCloud();
      TRTCReactNativeSdk.sharedInstance();
    }
    return this._trtcCloud;
  }
  /**
  Terminate TRTCCloud instance (singleton mode)
  */
  static destroySharedInstance() {
    this._trtcCloud = undefined;
    TRTCReactNativeSdk.destroySharedInstance();
  }

  /**
   * Add event
   * @param event
   * @param listener
   * @returns {{remove: remove}}
   */
  registerListener(listener: { (type: TRTCCloudListener, params: any): void }) {
    const callback = (args: { params: any; type: TRTCCloudListener }) => {
      let params;
      if (Platform.OS === 'android') {
        try {
          params = JSON.parse(args.params);
        } catch (e) {
          console.log(e);
        }
      } else {
        params = args.params;
      }
      listener(args.type, params);
    };
    TRTCEventEmitter.addListener('onListener', callback);
    this._listeners.set(listener, callback);
    return {
      remove: () => {
        this.unRegisterListener(listener);
      },
    };
  }

  /**
   * Removal
   * @param event
   * @param listener
   */
  unRegisterListener(listener: {
    (type: TRTCCloudListener, params: any): void;
  }) {
    const callback = this._listeners.get(listener);
    if (!callback) {
      return;
    }
    TRTCEventEmitter.removeAllListeners('onListener');
  }

  /**
   * Remove all events
   * @param event
   * @param listener
   */
  unRegisterAllListener() {
    this._listeners.clear();
    TRTCEventEmitter.removeAllListeners('onListener');
  }
  /**
  - Enter room
  - All TRTC users need to enter a room before they can "publish" or "subscribe to" audio/video streams. "Publishing" refers to pushing their own streams to the cloud, and "subscribing to" refers to pulling the streams of other users in the room from the cloud.
  - After calling this API, you will receive the  onEnterRoom(result)  callback from TRTCCloudListener:
    - If room entry succeeded, the  result  parameter will be a positive number ( result  > 0), indicating the time in milliseconds (ms) between function call and room entry.
    - If room entry failed, the  result  parameter will be a negative number ( result  < 0).
  @param param	Room entry parameter, which is used to specify the user's identity, role, authentication credentials, and other information.
  @param scene	Application scenario, currently supports four scenes: VideoCall, online live broadcast (LIVE), voice calls, and VoiceChatroom.
  */
  enterRoom(params: TRTCParams, scene: number): Promise<void> {
    if (Platform.OS === 'android') {
      return TRTCReactNativeSdk.enterRoom(
        {
          sdkAppId: params.sdkAppId,
          userId: params.userId,
          userSig: params.userSig,
          roomId: params.roomId!.toString(),
          strRoomId: params.strRoomId,
          role: params.role,
          streamId: params.streamId,
          userDefineRecordId: params.userDefineRecordId,
          privateMapKey: params.privateMapKey,
          businessInfo: params.businessInfo,
          scene: scene,
        },
        scene
      );
    }
    return TRTCReactNativeSdk.enterRoom(params, scene);
  }
  /**
  - Exit room
  - Calling this API will allow the user to leave the current audio or video room and release the camera, mic, speaker, and other device resources.
  - After resources are released, the SDK will use the  onExitRoom  callback in TRTCCloudListener to notify you.
  - If you need to call enterRoom again or switch to the SDK of another provider, we recommend you wait until you receive the  onExitRoom  callback, so as to avoid the problem of the camera or mic being occupied.
  */
  exitRoom(): Promise<void> {
    return TRTCReactNativeSdk.exitRoom();
  }
  /**
  - Get the sound management class TXAudioEffectManager.
  @return TXAudioEffectManager
  */
  getAudioEffectManager(): TXAudioEffectManager {
    TRTCReactNativeSdk.getAudioEffectManager();
    return new TXAudioEffectManager(TRTCReactNativeSdk);
  }

  /**
  - Get beauty management TXBeautyManager
  @return TXBeautyManager
  */
  getBeautyManager(): TXBeautyManager {
    TRTCReactNativeSdk.getBeautyManager();
    return new TXBeautyManager(TRTCReactNativeSdk);
  }

  /**
  - Get the management TXDeviceManager.
  @return TXDeviceManager
  */
  getDeviceManager(): TXDeviceManager {
    TRTCReactNativeSdk.getDeviceManager();
    return new TXDeviceManager(TRTCReactNativeSdk);
  }

  /**
  - Get the SDK version information
  @return Version number information
  */
  getSDKVersion(): Promise<string> {
    return TRTCReactNativeSdk.getSDKVersion();
  }

  /**
  - Set audio routing
  - Setting the "audio route" means setting whether the sound is played from the phone's speaker or receiver,
  - so this interface is only applicable to mobile devices such as mobile phones.
  @param route TRTC_AUDIO_ROUTE_SPEAKER or TRTC_AUDIO_ROUTE_EARPIECE, defalut is TRTC_AUDIO_ROUTE_SPEAKER.
  */
  setAudioRoute(route: number): Promise<void> {
    return TRTCReactNativeSdk.setAudioRoute({
      route: route,
    });
  }

  /**
  - Request cross-room call
  - By default, only users in the same room can make audio/video calls with each other, and the audio/video streams in different rooms are isolated from each other.
  - However, you can publish the audio/video streams of an anchor in another room to the current room by calling this API. At the same time, this API will also publish the local audio/video streams to the target anchor's room.
  - In other words, you can use this API to share the audio/video streams of two anchors in two different rooms, so that the audience in each room can watch the streams of these two anchors. This feature can be used to implement anchor competition.
  - The result of requesting cross-room call will be returned through the onConnectOtherRoom callback in TRTCCloudListener.
  - Call example:
    ```
      var object = new Map();
      object['roomId'] = 155;
      object['userId'] = '57890';
      trtcCloud.connectOtherRoom(jsonEncode(object));
    ```
  @param param	You need to pass in a string parameter in JSON format:  roomId  represents the room ID in numeric format,  strRoomId  represents the room ID in string format, and  userId  represents the user ID of the target anchor.
  */
  connectOtherRoom(param: string): Promise<void> {
    return TRTCReactNativeSdk.connectOtherRoom({
      param: param,
    });
  }
  /**
  - Exit cross-room call
  - The result will be returned through the  onDisconnectOtherRoom  callback in TRTCCloudListener.
  */
  disconnectOtherRoom(): Promise<void> {
    return TRTCReactNativeSdk.disconnectOtherRoom();
  }
  /**
  - Switch role
  - This API is used to switch the user role between  anchor  and  audience .
  - This API is only applicable to two scenarios: live streaming (TRTC_APP_SCENE_LIVE) and audio chat room (TRTC_APP_SCENE_VOICE_CHATROOM).
  - You can use the  role  field in TRTCParams during room entry to specify the user role in advance or use the  switchRole  API to switch roles after room entry.
  @param role	The target character is the anchor by default: TRTCCloudDef.TRTCRoleAnchor: anchor, you can go to video and audio. A room supports up to 50 anchors at the same time. TRTCCloudDef.TRTCRoleAudience: can only watch, not up upward video and audio, the number of audiences in a room is not limited.
  */
  switchRole(role: number): Promise<void> {
    return TRTCReactNativeSdk.switchRole({
      role: role,
    });
  }
  /**
  - Set subscription mode (which must be set before room entry for it to take effect)
  - You can switch between the "automatic subscription" and "manual subscription" modes through this API:
    - Automatic subscription: this is the default mode, where the user will immediately receive the audio/video streams in the room after room entry, so that the audio will be automatically played back, and the video will be automatically decoded (you still need to bind the rendering control through the  startRemoteView  API).
    - Manual subscription: after room entry, the user needs to manually call the startRemoteView API to start subscribing to and decoding the video stream and call the muteRemoteAudio(false) API to start playing back the audio stream.
  @param autoRecvAudio	true: automatic subscription to audio; false: manual subscription to audio by calling  muteRemoteAudio(false) . Default value: true
  @param autoRecvVideo true: automatic subscription to video; false: manual subscription to video by calling  startRemoteView . Default value: true
  */
  setDefaultStreamRecvMode(
    autoRecvAudio: boolean,
    autoRecvVideo: boolean
  ): Promise<void> {
    return TRTCReactNativeSdk.setDefaultStreamRecvMode({
      autoRecvAudio: autoRecvAudio,
      autoRecvVideo: autoRecvVideo,
    });
  }
  /**
  - Switch room
  - This API is used to quickly switch a user from one room to another.
    - If the user's role is `audience`, calling this API is equivalent to  exitRoom  (current room) +  enterRoom  (new room).
    - If the user's role is `anchor`, the API will retain the current audio/video publishing status while switching the room; therefore, during the room switch, camera preview and sound capturing will not be interrupted.
  - This API is suitable for the online education scenario where the supervising teacher can perform fast room switch across multiple rooms. In this scenario, using  switchRoom  can get better smoothness and use less code than  exitRoom + enterRoom .
  - The API call result will be called back through  onSwitchRoom(errCode, errMsg)  in TRTCCloudListener.
  @param config	Room parameter. For more information, please see TRTCSwitchRoomConfig.
  */
  switchRoom(config: TRTCSwitchRoomConfig): Promise<void> {
    return TRTCReactNativeSdk.switchRoom({
      config: JSON.stringify(config),
    });
  }

  /**
  - Set placeholder image during local video pause
  - When you call  muteLocalVideo(true)  to pause the local video image, you can set a placeholder image by calling this API. Then, other users in the room will see this image instead of a black screen.
  - @param image Set the picture to be pushed. "" Means not pushing
  - @param fps	 Frame rate of the placeholder image. Minimum value: 5. Maximum value: 10. Default value: 5
  */
  setVideoMuteImage(image: string, fps: number): Promise<void> {
    return TRTCReactNativeSdk.setVideoMuteImage({
      imageUrl: image,
      fps,
    });
  }

  /**
  - Add watermark
  - The watermark position is determined by the  rect  parameter, which is a quadruple in the format of (x, y, width, height).
    - x: X coordinate of watermark, which is a floating-point number between 0 and 1.
    - y: Y coordinate of watermark, which is a floating-point number between 0 and 1.
    - width: width of watermark, which is a floating-point number between 0 and 1.
    - height: it does not need to be set. The SDK will automatically calculate it according to the watermark image's aspect ratio.
  - Sample parameter:
    - If the encoding resolution of the current video is 540x960, and the  rect  parameter is set to (0.1, 0.1, 0.2, 0.0), then the coordinates of the top-left point of the watermark will be (540 * 0.1, 960 * 0.1), i.e., (54, 96), the watermark width will be 540 * 0.2 = 108 px, and the watermark height will be calculated automatically by the SDK based on the watermark image's aspect ratio.
  - @param  image Watermark image, which must be a PNG image with transparent background
  - @param  streamType	Specify for which image to set the watermark.
  - @param  rect Unified coordinates of the watermark relative to the encoded resolution. Value range of  x ,  y ,  width , and  height : 0–1.
  */
  setWatermark(
    image: string,
    streamType: number,
    x: number,
    y: number,
    width: number
  ): Promise<void> {
    return TRTCReactNativeSdk.setWatermark({
      imageUrl: image,
      streamType,
      x: x.toString(),
      y: y.toString(),
      width: width.toString(),
    });
  }

  /**
  - Start publishing audio/video streams to Tencent Cloud CSS CDN
  - This API sends a command to the TRTC server, requesting it to relay the current user's audio/video streams to CSS CDN.
  - You can set the  StreamId  of the live stream through the  streamId  parameter, so as to specify the playback address of the user's audio/video streams on CSS CDN.
  - For example, if you specify the current user's live stream ID as  user_stream_001  through this API, then the corresponding CDN playback address is: "http://yourdomain/live/user_stream_001.flv", where  yourdomain  is your playback domain name with an ICP filing.
  - You can configure your playback domain name in the [CSS console](https://console.tencentcloud.com/live). Tencent Cloud does not provide a default playback domain name.
  - You can also specify the  streamId  when setting the  TRTCParams  parameter of  enterRoom , which is the recommended approach.
  @param  streamId	  Custom stream ID.
  @param  streamType	Only TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG and TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SUB are supported.
  - Note:
  - You need to enable the "Enable Relayed Push" option on the "Function Configuration" page in the [TRTC console](https://console.tencentcloud.com/trtc/) in advance.
    - If you select "Specified stream for relayed push", you can use this API to push the corresponding audio/video stream to Tencent Cloud CDN and specify the entered stream ID.
    - If you select "Global auto-relayed push", you can use this API to adjust the default stream ID.
  */
  startPublishing(streamId: string, streamType: number): Promise<void> {
    return TRTCReactNativeSdk.startPublishing({
      streamId: streamId,
      streamType: streamType,
    });
  }
  /**
  - Stop publishing audio/video streams to Tencent Cloud CSS CDN
  */
  stopPublishing(): Promise<void> {
    return TRTCReactNativeSdk.stopPublishing();
  }
  /**
  - Start publishing audio/video streams to non-Tencent Cloud CDN
  - This API is similar to the  startPublishing  API. The difference is that  startPublishing  can only publish audio/video streams to Tencent Cloud CDN, while this API can relay streams to live streaming CDN services of other cloud providers.
  @param	param CDN relaying parameter. For more information, please see TRTCPublishCDNParam
  - Note:
    - Using the `startPublishing` API to publish audio/video streams to Tencent Cloud CSS CDN does not incur additional fees.
    - Using the `startPublishCDNStream` API to publish audio/video streams to non-Tencent Cloud CDN incurs additional relaying bandwidth fees.
  */
  startPublishCDNStream(param: TRTCPublishCDNParam): Promise<void> {
    return TRTCReactNativeSdk.startPublishCDNStream({
      param: JSON.stringify(param),
    });
  }
  /**
  - Stop publishing audio/video streams to non-Tencent Cloud CDN
  */
  stopPublishCDNStream(): Promise<void> {
    return TRTCReactNativeSdk.stopPublishCDNStream();
  }

  /**
  - Set the layout and transcoding parameters of On-Cloud MixTranscoding
  - In a live room, there may be multiple anchors publishing their audio/video streams at the same time, but for audience on CSS CDN, they only need to watch one video stream in HTTP-FLV or HLS format.
  - When you call this API, the SDK will send a command to the TRTC mixtranscoding server to combine multiple audio/video streams in the room into one stream.
  - You can use the `TRTCTranscodingConfig` parameter to set the layout of each channel of image. You can also set the encoding parameters of the mixed audio/video streams.
  - For more information, please see [On-Cloud MixTranscoding](https://www.tencentcloud.com/document/product/647/34618).
  @param  config If `config` is not empty, On-Cloud MixTranscoding will be started; otherwise, it will be stopped.
  */
  setMixTranscodingConfig(config: TRTCTranscodingConfig): Promise<void> {
    return TRTCReactNativeSdk.setMixTranscodingConfig({
      config: JSON.stringify(config),
    });
  }

  /**
  - Pause/Resume publishing local video stream
  - After local video publishing is paused, other members in the same room will receive the  onUserVideoAvailable(userId, false)  callback notification.
  - After local video publishing is resumed, other members in the same room will receive the  onUserVideoAvailable(userId, true)  callback notification.
  */
  muteLocalVideo(mute: boolean): Promise<void> {
    return TRTCReactNativeSdk.muteLocalVideo({ mute: mute });
  }

  /**
  - Pause/Resume subscribing to remote user's video stream
  - This API only pauses/resumes receiving the specified user's video stream but does not release displaying resources; therefore, the video image will freeze at the last frame before it is called.
  @param userId	ID of the specified remote user
  @param mute	Whether to pause receiving
  */
  muteRemoteVideoStream(userId: string, mute: boolean): Promise<void> {
    return TRTCReactNativeSdk.muteRemoteVideoStream({
      userId,
      mute,
    });
  }

  /**
  - Set the rendering mode of remote video image
  - The parameters that can be set include video image rotation angle, fill mode, and mirror mode.
  @param userId	ID of the specified remote user
  @param streamType	It can be set to the primary stream image (TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG) or substream image (TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SUB).
  @param param	Video image rendering parameters. 
  */
  setRemoteRenderParams(
    userId: string,
    streamType: number,
    param: TRTCRenderParams
  ): Promise<void> {
    return TRTCReactNativeSdk.setRemoteRenderParams({
      userId,
      streamType,
      param: JSON.stringify(param),
    });
  }

  /**
  - Set the encoding parameters of video encoder
  - This setting can determine the quality of image viewed by remote users, which is also the image quality of on-cloud recording files.
  @param param	It is used to set relevant parameters for the video encoder. For more information, please see TRTCVideoEncParam。
  */
  setVideoEncoderParam(param: TRTCVideoEncParam): Promise<void> {
    return TRTCReactNativeSdk.setVideoEncoderParam({
      param: JSON.stringify(param),
    });
  }

  /**
  - Set network quality control parameters
  - This setting determines the quality control policy in a poor network environment, such as "image quality preferred" or "smoothness preferred".
  @param param It is used to set relevant parameters for network quality control.
  */
  setNetworkQosParam(param: TRTCNetworkQosParam): Promise<void> {
    return TRTCReactNativeSdk.setNetworkQosParam({
      param: JSON.stringify(param),
    });
  }

  /**
  - Set the direction of image output by video encoder
  - When the user's mobile phone or Android Pad made a 180 -degree rotation, because the collection direction of the camera has not changed, the screen that users on the other side are reversed. In this case, you can use the interface to SDK through this interface SDK The output to the other party rotates 180 degrees, so that the screen that the other party can see is still normal.
  - TRTCCloudDef.TRTC_VIDEO_ROTATION_0 Do not rotate (default)
  - TRTCCloudDef.TRTC_VIDEO_ROTATION_180 Rotate 180 degrees clockwise
  @param rotation	Currently supports two rotation angles of 0 and 180, the default value: TRTCVideorotation_0
  */
  setVideoEncoderRotation(rotation: number): Promise<void> {
    return TRTCReactNativeSdk.setVideoEncoderRotation({
      rotation,
    });
  }

  /**
  - Set the mirror mode of image output by encoder
  - The interface does not change the preview screen of the local camera, but it will change the effect of the screen (and the server recording) of the user.
  @param mirror	true: mirror; false: No mirror; default value: false
  */
  setVideoEncoderMirror(mirror: boolean): Promise<void> {
    return TRTCReactNativeSdk.setVideoEncoderMirror({
      mirror,
    });
  }

  /**
  - Set the adaptation mode of G-sensor
  @param mode	Gravity induction mode:
  - TRTCCloudDef.TRTC_GSENSOR_MODE_DISABLE : Close gravity response
  - TRTCCloudDef.TRTC_GSENSOR_MODE_UIFIXLAYOUT : Open the gravity induction, SDK will automatically adjust the rotation direction of the remote user and the local view screen.
  - TRTCCloudDef.TRTC_GSENSOR_MODE_UIAUTOLAYOUT: Turn off the gravity sensing, SDK will automatically adjust the direction of the picture seen by the remote user, but it will not adjust the rotation direction of the local view screen. If your APP interface opens a gravity induction adaptation option, it is recommended to select this mode, otherwise the SDK direction adjustment logic will conflict with the system.
  */
  setGSensorMode(mode: number): Promise<void> {
    return TRTCReactNativeSdk.setGSensorMode({
      mode,
    });
  }

  /**
  - Pause/Resume subscribing to all remote users' video streams
  - This API only pauses/resumes receiving all users' video streams but does not release displaying resources; therefore, the video image will freeze at the last frame before it is called.
  @param mute	Whether to suspend receiving
  */
  muteAllRemoteVideoStreams(mute: boolean): Promise<void> {
    return TRTCReactNativeSdk.muteAllRemoteVideoStreams({
      mute,
    });
  }

  /**
  - Enable local audio capturing and publishing
  - The SDK does not enable the mic by default. When a user wants to publish the local audio, the user needs to call this API to enable mic capturing and encode and publish the audio to the current room.
  - After local audio capturing and publishing is enabled, other users in the room will receive the onUserAudioAvailable(userId, true) notification.
  @param quality	Sound quality
  - TRTCAudioQualitySpeech - Smooth: sample rate: 16 kHz; mono channel; audio bitrate: 16 Kbps. This is suitable for audio call scenarios, such as online meeting and audio call.
  - TRTCAudioQualityDefault - Default: sample rate: 48 kHz; mono channel; audio bitrate: 50 Kbps. This is the default sound quality of the SDK and recommended if there are no special requirements.
  - TRTCAudioQualityMusic - HD: sample rate: 48 kHz; dual channel + full band; audio bitrate: 128 Kbps. This is suitable for scenarios where Hi-Fi music transfer is required, such as online karaoke and music live streaming.
  */
  startLocalAudio(quality: number): Promise<void> {
    return TRTCReactNativeSdk.startLocalAudio({ quality: quality });
  }
  /**
  - Stop local audio capturing and publishing
  - After local audio capturing and publishing is stopped, other users in the room will receive the onUserAudioAvailable(userId, false) notification.
  */
  stopLocalAudio(): Promise<void> {
    return TRTCReactNativeSdk.stopLocalAudio();
  }

  /**
  - Stop camera preview
  */
  stopLocalPreview(): Promise<void> {
    return TRTCReactNativeSdk.stopLocalPreview();
  }

  /**
  - Stop subscribing to remote user's video stream and release rendering control
  @param streamType	Only TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG and TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SUB are supported;
  */
  stopRemoteView(userId: String, streamType: number): Promise<void> {
    return TRTCReactNativeSdk.stopRemoteView({
      userId: userId,
      streamType: streamType,
    });
  }

  /**
  - Pause/Resume publishing local audio stream
  - After local audio publishing is paused, other users in the room will receive the onUserAudioAvailable(userId, false) notification.
  - After local audio publishing is resumed, other users in the room will receive the onUserAudioAvailable(userId, true) notification.
  - Different from stopLocalAudio,  muteLocalAudio(true)  does not release the mic permission; instead, it continues to send mute packets with extremely low bitrate.
  - This is very suitable for scenarios that require on-cloud recording, as video file formats such as MP4 have a high requirement for audio continuity, while an MP4 recording file cannot be played back smoothly if stopLocalAudio is used.
  @param mute	true: mute; false: unmute
  */
  muteLocalAudio(mute: boolean): Promise<void> {
    return TRTCReactNativeSdk.muteLocalAudio({
      mute: mute,
    });
  }
  /**
  - Pause/Resume playing back remote audio stream
  @param userId	ID of the specified remote user
  @param mute	true: mute; false: unmute
  - Note: This API works when called either before or after room entry (enterRoom), and the mute status will be reset to  false  after room exit (exitRoom).
  */
  muteRemoteAudio(userId: string, mute: boolean): Promise<void> {
    return TRTCReactNativeSdk.muteRemoteAudio({
      userId: userId,
      mute: mute,
    });
  }
  /**
  - Pause/Resume playing back all remote users' audio streams
  @param mute	true: mute; false: unmute
  - Note: This API works when called either before or after room entry (enterRoom), and the mute status will be reset to  false  after room exit (exitRoom).
  */
  muteAllRemoteAudio(mute: boolean): Promise<void> {
    return TRTCReactNativeSdk.muteAllRemoteAudio({
      mute: mute,
    });
  }
  /**
  - Set the audio playback volume of remote user
  @param userId	ID of the specified remote user
  @param volume	Volume. 100 is the original volume. Value range: [0,150]. Default value: 100
  */
  setRemoteAudioVolume(userId: string, volume: number): Promise<void> {
    return TRTCReactNativeSdk.setRemoteAudioVolume({
      userId: userId,
      volume: volume,
    });
  }
  /**
  - Set the capturing volume of local audio
  @param volume	Volume. 100 is the original volume. Value range: [0,150]. Default value: 100
  */
  setAudioCaptureVolume(volume: number): Promise<void> {
    return TRTCReactNativeSdk.setAudioCaptureVolume({
      volume: volume,
    });
  }
  /**
  - Get the capturing volume of local audio
  */
  getAudioCaptureVolume(): Promise<number> {
    return TRTCReactNativeSdk.getAudioCaptureVolume();
  }
  /**
  - Set the playback volume of remote audio
  - This API controls the volume of the sound ultimately delivered by the SDK to the system for playback. It affects the volume of the recorded local audio file but not the volume of in-ear monitoring.
  @param volume	Volume. 100 is the original volume. Value range: [0,150]. Default value: 100
  */
  setAudioPlayoutVolume(volume: number): Promise<void> {
    return TRTCReactNativeSdk.setAudioPlayoutVolume({
      volume: volume,
    });
  }
  /**
  - Get the playback volume of remote audio
  */
  getAudioPlayoutVolume(): Promise<number> {
    return TRTCReactNativeSdk.getAudioPlayoutVolume();
  }
  /**
  - Enable volume reminder
  - After this feature is enabled, the SDK will return the audio volume assessment information of local user who sends stream and remote users in the onUserVoiceVolume callback of TRTCCloudListener
  @param intervalMs	The trigger interval of the onsetVolume callback is determined. The unit is MS and the minimum interval is 100ms. If it is less than or equal to 0, the callback is closed. It is recommended to set it to 300ms. For detailed callback rules
  */
  enableAudioVolumeEvaluation(intervalMs: number): Promise<void> {
    return TRTCReactNativeSdk.enableAudioVolumeEvaluation({
      intervalMs: intervalMs,
    });
  }
  /**
  - Start audio recording
  - After you call this API, the SDK will selectively record local and remote audio streams (such as local audio, remote audio, background music, and sound effects) into a local file.
  - This API works when called either before or after room entry. If a recording task has not been stopped through  stopAudioRecording  before room exit, it will be automatically stopped after room exit.
  - The startup and completion status of the recording will be notified through local recording-related callbacks. See TRTCCloud related callbacks for reference.
  @param pram Recording parameter. 
  @return 0: success; -1: audio recording has been started; -2: failed to create file or directory; -3: the audio format of the specified file extension is not supported.
  */
  startAudioRecording(param: TRTCAudioRecordingParams): Promise<number> {
    return TRTCReactNativeSdk.startAudioRecording({
      param: param,
    });
  }
  /**
  - Stop audio recording
  - If a recording task has not been stopped through this API before room exit, it will be automatically stopped after room exit.
  */
  stopAudioRecording(): Promise<void> {
    return TRTCReactNativeSdk.stopAudioRecording();
  }
  /**
  - Enable 3D spatial effect
  - Enable 3D spatial effect. Note that TRTCAudioQualitySpeech smooth or TRTCAudioQualityDefault. default audio quality should be used.
  @param enabled	Whether to enable 3D spatial effect. It's disabled by default.
  */
  enable3DSpatialAudioEffect(enabled: boolean): Promise<void> {
    return TRTCReactNativeSdk.enable3DSpatialAudioEffect({
      enabled: enabled,
    });
  }
  /**
  - Update self position and orientation for 3D spatial effect
  - Update self position and orientation in the world coordinate system. The SDK will calculate the relative position between self and the remote users according to the parameters of this method, and then render the spatial sound effect. Note that the length of array should be 3.
  @param position	The coordinate of self in the world coordinate system. The three values represent the forward, right and up coordinate values in turn.
  @param axisForward	The unit vector of the forward axis of user coordinate system. The three values represent the forward, right and up coordinate values in turn.
  @param axisRight	The unit vector of the right axis of user coordinate system. The three values represent the forward, right and up coordinate values in turn.
  @param axisUp	The unit vector of the up axis of user coordinate system. The three values represent the forward, right and up coordinate values in turn.
  */
  updateSelf3DSpatialPosition(
    position: number[],
    axisForward: number[],
    axisRight: number[],
    axisUp: number[]
  ): Promise<void> {
    return TRTCReactNativeSdk.updateSelf3DSpatialPosition({
      position: position.map((p) => p.toString()),
      axisForward: axisForward.map((a) => a.toString()),
      axisRight: axisRight.map((a) => a.toString()),
      axisUp: axisUp.map((a) => a.toString()),
    });
  }
  /**
  - Update the specified remote user's position for 3D spatial effect
  - Update the specified remote user's position in the world coordinate system. The SDK will calculate the relative position between self and the remote users according to the parameters of this method, and then render the spatial sound effect. Note that the length of array should be 3.
  @param userId	ID of the specified remote user.
  @param position	The coordinate of self in the world coordinate system. The three values represent the forward, right and up coordinate values in turn.
  */
  updateRemote3DSpatialPosition(
    userId: string,
    position: number[]
  ): Promise<void> {
    return TRTCReactNativeSdk.updateRemote3DSpatialPosition({
      userId: userId,
      position: position.map((p) => p.toString()),
    });
  }
  /**
  - Set the maximum 3D spatial attenuation range for userId's audio stream
  - After set the range, the specified user's audio stream will attenuate to zero within the range.
  @param userId	ID of the specified user.
  @param range	Maximum attenuation range of the audio stream.
  */
  set3DSpatialReceivingRange(userId: string, range: number): Promise<void> {
    return TRTCReactNativeSdk.set3DSpatialReceivingRange({
      userId: userId,
      range: range,
    });
  }
  /**
  - Start network speed test (used before room entry)
  @param sdkAppId	Application logo
  @param userId	User logo
  @param userSig	User signature
  */
  startSpeedTest(
    param: TRTCSpeedTestParams
  ): Promise<void> {
    console.log('startSpeedTest', param);
    return TRTCReactNativeSdk.startSpeedTest({
      expectedDownBandwidth: param.expectedDownBandwidth,
      expectedUpBandwidth: param.expectedUpBandwidth,
      scene: param.scene,
      sdkAppId: param.sdkAppId,
      userId: param.userId,
      userSig: param.userSig,
    });
  }

  /**
  - Stop network speed test
  */
  stopSpeedTest(): Promise<void> {
    return TRTCReactNativeSdk.stopSpeedTest();
  }

  /**
  - Send SEI Message
  This API has the following restrictions:
  1. The data will not be instantly sent after this API is called; instead, it will be inserted into the next video frame after the API call.
  2. Up to 30 messages can be sent per second to all users in the room (this limit is shared with  sendCustomCmdMsg ).
  3. Each packet can be up to 1 KB (this limit is shared with  sendCustomCmdMsg ). If a large amount of data is sent, the video bitrate will increase, which may reduce the video quality or even cause lagging.
  4. Each client can send up to 8 KB of data in total per second (this limit is shared with  sendCustomCmdMsg ).
  5. If multiple times of sending is required (i.e.,  repeatCount  > 1), the data will be inserted into subsequent  repeatCount  video frames in a row for sending, which will increase the video bitrate.
  6. If  repeatCount  is greater than 1, the data will be sent for multiple times, and the same message may be received multiple times in the  onRecvSEIMsg  callback; therefore, deduplication is required.

  @param buffer	Data to be sent, which can be up to 1 KB (1,000 bytes)
  @param repeatCount	Data sending count
  */
  sendSEIMsg(message: string, repeatCount: number): Promise<void> {
    return TRTCReactNativeSdk.sendSEIMsg({ message: message, repeatCount: repeatCount });
  }

  /**
  - Send Custom Message
  Use UDP channel to send custom message to all users in room
  This API allows you to use TRTC's UDP channel to broadcast custom data to other users in the current room for signaling transfer.
  Other users in the room can receive the message through the onRecvCustomCmdMsg callback in TRTCCloudListener.
  
  @param cmdID Message ID. Value range: 1–10.
  @param data Message to be sent. The maximum length of one single message is 1 KB.
  @param reliable Whether reliable sending is enabled. Reliable sending can achieve a higher success rate but with a longer reception delay than unreliable sending.
  @param ordered Whether orderly sending is enabled, i.e., whether the data packets should be received in the same order in which they are sent; if so, a certain delay will be caused.
  */
  sendCustomCmdMsg(cmdID: number, data: string, reliable: boolean, ordered: boolean) {
    return TRTCReactNativeSdk.sendCustomCmdMsg({
      cmdID: cmdID, 
      data: data, 
      reliable: reliable,
      ordered: ordered,
    });
  }

  /**
  - Set log output level
  @param level	For more information, please see TRTC_LOG_LEVEL; Default value: TRTCCloudDef.TRTC_LOG_LEVEL_NULL
  */
  setLogLevel(level: number): Promise<void> {
    return TRTCReactNativeSdk.setLogLevel({ level: level });
  }
  /**
  - Enable/Disable console log printing
  @param enabled	Specify whether to enable it, which is disabled by default
  */
  setConsoleEnabled(enabled: boolean): Promise<void> {
    return TRTCReactNativeSdk.setConsoleEnabled({
      enabled: enabled,
    });
  }
  /**
  - Enable/Disable local log compression
  - If compression is enabled, the log size will significantly reduce, but logs can be read only after being decompressed by the Python script provided by Tencent Cloud.
  - If compression is disabled, logs will be stored in plaintext and can be read directly in Notepad, but will take up more storage capacity.
  @param enabled	Specify whether to enable it, which is enabled by default
  */
  setLogCompressEnabled(enabled: boolean): Promise<void> {
    return TRTCReactNativeSdk.setLogCompressEnabled({
      enabled: enabled,
    });
  }
  /**
  - Set local log storage path
  - You can use this API to change the default storage path of the SDK's local logs, which is as follows:
    - iOS or macOS: under  sandbox Documents/log .
    - Android: under  /app directory/files/log/liteav/ .
  @param path Log storage path
  */
  setLogDirPath(path: string): Promise<void> {
    return TRTCReactNativeSdk.setLogDirPath({
      path: path,
    });
  }
  /**
   - Start local media recording. 
   - @param param Recording parameters. Please refer to TRTCLocalRecordingParams.
   */
  startLocalRecording(param: TRTCLocalRecordingParams): Promise<void> {
    const finalParam = {
      filePath: param.filePath ?? '',
      recordType: param.recordType ?? TRTCRecordType.TRTCRecordTypeBoth,
      interval: param.interval ?? -1,
      maxDurationPerFile: param.maxDurationPerFile ?? 0,
    };
    return TRTCReactNativeSdk.startLocalRecording({
      param: JSON.stringify(finalParam),
    });
  }
  /**
   - Stop local media recording. 
  */
  stopLocalRecording(): Promise<void> {
    return TRTCReactNativeSdk.stopLocalRecording();
  }
  /**
  - Call experimental APIs
  - Note: This interface is used to call some experimental functions
  @param jsonStr	JSON string described by interface and parameter description
  */
  callExperimentalAPI(jsonStr: string): Promise<void> {
    return TRTCReactNativeSdk.callExperimentalAPI({
      jsonStr: jsonStr,
    });
  }
}
export {
  TXVideoView,
  TRTCParams,
  TRTCCloudDef,
  TXVoiceChangerType,
  TXVoiceReverbType,
  TRTCCloudListener,
  TXSystemVolumeType,
  TRTCRecordType,
};

export type {
  TRTCSwitchRoomConfig,
  TRTCPublishCDNParam,
  TRTCAudioRecordingParams,
  TRTCLocalRecordingParams,
  AudioMusicParam,
  TRTCVideoEncParam,
  TRTCNetworkQosParam,
  TRTCTranscodingConfig,
};