// ignore_for_file: non_constant_identifier_names, camel_case_types, missing_return, unused_import, unused_local_variable, dead_code, unnecessary_cast
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:foundation_fluttify/foundation_fluttify.dart';
import 'package:tencent_live_fluttify/src/android/android.export.g.dart';
import 'package:tencent_live_fluttify/src/ios/ios.export.g.dart';

import 'cloud_video_controller.dart';
import 'enums.dart';

part 'pusher_delegates.dart';

/// 推流控制器
class LivePusher extends _Holder with _Community, _Pro {
  LivePusher._();

  static Future<LivePusher> create({bool enableTouchFocus}) async {
    return platform(
      android: (pool) async {
        final instance = LivePusher._();

        instance._androidConfig =
            await com_tencent_rtmp_TXLivePushConfig.create__();
        if (enableTouchFocus != null) {
          await instance._androidConfig.setTouchFocus(enableTouchFocus);
        }

        final context = await android_app_Application.get();
        instance._androidPusher = await com_tencent_rtmp_TXLivePusher
            .create__android_content_Context(context);

        await instance._androidPusher.setConfig(instance._androidConfig);

        return instance;
      },
      ios: (pool) async {
        final instance = LivePusher._();

        instance._iOSConfig = await TXLivePushConfig.create__();
        if (enableTouchFocus != null) {
          await instance._iOSConfig.set_touchFocus(enableTouchFocus);
        }

        instance._iosPusher = await TXLivePush.create__();

        await instance._iosPusher.initWithConfig(instance._iOSConfig);
        return instance;
      },
    );
  }

  /// 事件处理
  ///
  /// [onWaringNetBusy]弱网提醒
  Future<void> setOnEventListener({
    VoidCallback onWaringNetBusy,
    VoidCallback onWaringReconnect,
    VoidCallback onWaringHardwareAccelerationFail,
    VoidCallback onWaringDNSFail,
    VoidCallback onWaringServerConnFail,
    VoidCallback onWaringShakeFail,
    VoidCallback onWaringServerDisconnect,
    VoidCallback onEventConnectSucc,
    VoidCallback onEventPushBegin,
    VoidCallback onEventOpenCameraSuccess,
    VoidCallback onErrorOpenCameraFail,
    VoidCallback onErrorOpenMicFail,
    VoidCallback onErrorVideoEncodeFail,
    VoidCallback onErrorAudioEncodeFail,
    VoidCallback onErrorUnsupportedResolution,
    VoidCallback onErrorUnsupportedSampleRate,
    VoidCallback onErrorNetDisconnect,
  }) async {
    return platform(
      android: (pool) async {
        _androidPusher.setPushListener(
          _androidEventDelegate
            .._onWaringNetBusy = onWaringNetBusy
            .._onWaringReconnect = onWaringReconnect
            .._onWaringHardwareAccelerationFail =
                onWaringHardwareAccelerationFail
            .._onWaringDNSFail = onWaringDNSFail
            .._onWaringServerConnFail = onWaringServerConnFail
            .._onWaringShakeFail = onWaringShakeFail
            .._onWaringServerDisconnect = onWaringServerDisconnect
            .._onEventConnectSucc = onEventConnectSucc
            .._onEventPushBegin = onEventPushBegin
            .._onEventOpenCameraSuccess = onEventOpenCameraSuccess
            .._onErrorOpenCameraFail = onErrorOpenCameraFail
            .._onErrorOpenMicFail = onErrorOpenMicFail
            .._onErrorVideoEncodeFail = onErrorVideoEncodeFail
            .._onErrorAudioEncodeFail = onErrorAudioEncodeFail
            .._onErrorUnsupportedResolution = onErrorUnsupportedResolution
            .._onErrorUnsupportedSampleRate = onErrorUnsupportedSampleRate
            .._onErrorNetDisconnect = onErrorNetDisconnect,
        );
      },
      ios: (pool) async {
        _iosPusher.set_delegate(
          _iosEventDelegate
            .._onWaringNetBusy = onWaringNetBusy
            .._onWaringReconnect = onWaringReconnect
            .._onWaringHardwareAccelerationFail =
                onWaringHardwareAccelerationFail
            .._onWaringDNSFail = onWaringDNSFail
            .._onWaringServerConnFail = onWaringServerConnFail
            .._onWaringShakeFail = onWaringShakeFail
            .._onWaringServerDisconnect = onWaringServerDisconnect
            .._onEventConnectSucc = onEventConnectSucc
            .._onEventPushBegin = onEventPushBegin
            .._onEventOpenCameraSuccess = onEventOpenCameraSuccess
            .._onErrorOpenCameraFail = onErrorOpenCameraFail
            .._onErrorOpenMicFail = onErrorOpenMicFail
            .._onErrorVideoEncodeFail = onErrorVideoEncodeFail
            .._onErrorAudioEncodeFail = onErrorAudioEncodeFail
            .._onErrorUnsupportedResolution = onErrorUnsupportedResolution
            .._onErrorUnsupportedSampleRate = onErrorUnsupportedSampleRate
            .._onErrorNetDisconnect = onErrorNetDisconnect,
        );
      },
    );
  }
}

mixin _Community on _Holder {
  /// 开始预览
  Future<void> startPreview(CloudVideoController preview) async {
    return platform(
      android: (pool) async {
        await _androidPusher.startCameraPreview(preview.playerView);
      },
      ios: (pool) async {
        await _iosPusher.startPreview(preview.playerView);
      },
    );
  }

  /// 开始推流
  Future<void> startPush(String pushUrl) async {
    return platform(
      android: (pool) async {
        final result = await _androidPusher.startPusher(pushUrl);
        debugPrint('result: $result');
      },
      ios: (pool) async {
        final result = await _iosPusher.startPush(pushUrl);
        debugPrint('result: $result');
      },
    );
  }

  /// 暂停推流
  Future<void> pausePush() async {
    return platform(
      android: (pool) => _androidPusher.pausePusher(),
      ios: (pool) => _iosPusher.pausePush(),
    );
  }

  /// 恢复推流
  Future<void> resumePush() async {
    return platform(
      android: (pool) => _androidPusher.resumePusher(),
      ios: (pool) => _iosPusher.resumePush(),
    );
  }

  /// 停止预览
  Future<void> stopPreview() async {
    return platform(
      android: (pool) => _androidPusher.stopCameraPreview(true),
      ios: (pool) => _iosPusher.stopPreview(),
    );
  }

  /// 停止推流
  Future<void> stopPush() async {
    return platform(
      android: (pool) => _androidPusher.stopPusher(),
      ios: (pool) => _iosPusher.stopPush(),
    );
  }

  /// 切换前后摄像头
  Future<void> switchCamera() async {
    return platform(
      android: (pool) => _androidPusher.switchCamera(),
      ios: (pool) => _iosPusher.switchCamera(),
    );
  }

  /// 打开/关闭闪光灯
  ///
  /// 仅在当前是后置摄像头时有效
  Future<void> turnFlashLight(bool on) async {
    return platform(
      android: (pool) => _androidPusher.turnOnFlashLight(on),
      ios: (pool) => _iosPusher.toggleTorch(on),
    );
  }

  /// 播放背景音乐
  ///
  /// 调用 TXLivePush 中的 BGM 相关接口可以实现背景混音功能。背景混音是指主播在直播时可以选取一首歌曲伴唱，
  /// 歌曲会在主播的手机端播放出来，同时也会被混合到音视频流中被观众端听到，所以被称为“混音”
  Future<void> playBGM(String path) async {
    return platform(
      android: (pool) => _androidPusher.playBGM(path),
      ios: (pool) => _iosPusher.playBGM(path),
    );
  }

  /// 停止背景音乐
  Future<void> stopBGM() async {
    return platform(
      android: (pool) => _androidPusher.stopBGM(),
      ios: (pool) => _iosPusher.stopBGM(),
    );
  }

  /// 暂停背景音乐
  Future<void> pauseBGM() async {
    return platform(
      android: (pool) => _androidPusher.pauseBGM(),
      ios: (pool) => _iosPusher.pauseBGM(),
    );
  }

  /// 恢复背景音乐
  Future<void> resumeBGM() async {
    return platform(
      android: (pool) => _androidPusher.resumeBGM(),
      ios: (pool) => _iosPusher.resumeBGM(),
    );
  }

  /// 麦克风音量大小
  Future<void> setMicVolume(double volume) async {
    return platform(
      android: (pool) => _androidPusher.setMicVolume(volume),
      ios: (pool) => _iosPusher.setMicVolume(volume),
    );
  }

  /// 背景音乐音量大小
  Future<void> setBGMVolume(double volume) async {
    return platform(
      android: (pool) => _androidPusher.setBGMVolume(volume),
      ios: (pool) => _iosPusher.setBGMVolume(volume),
    );
  }

  /// 背景音乐音调高低
  Future<void> setBgmPitch(double level) async {
    return platform(
      android: (pool) => _androidPusher.setBGMPitch(level),
      ios: (pool) => _iosPusher.setBGMPitch(level),
    );
  }

  Future<void> dispose() async {
    return platform(
      android: (pool) async {
        await _androidPusher.release__();
      },
      ios: (pool) async {
        await _iosPusher.release__();
      },
    );
  }
}

mixin _Pro on _Holder {
  /// 设置观众看到的画面清晰度
  ///
  /// [quality]画面清晰度, [adjustBitrate]是否根据网络状态自动调整画质
  Future<void> setVideoQuality(
    Quality quality, {
    bool adjustBitrate = true,
  }) async {
    return platform(
      android: (pool) async {
        int androidQuality =
            com_tencent_rtmp_TXLiveConstants.VIDEO_QUALITY_HIGH_DEFINITION;
        switch (quality) {
          case Quality.STANDARD:
            androidQuality = com_tencent_rtmp_TXLiveConstants
                .VIDEO_QUALITY_STANDARD_DEFINITION;
            break;
          case Quality.HIGH:
            androidQuality =
                com_tencent_rtmp_TXLiveConstants.VIDEO_QUALITY_HIGH_DEFINITION;
            break;
          case Quality.SUPER_HIGH:
            androidQuality =
                com_tencent_rtmp_TXLiveConstants.VIDEO_QUALITY_SUPER_DEFINITION;
            break;
          case Quality.LINKMIC_MAIN:
            androidQuality = com_tencent_rtmp_TXLiveConstants
                .VIDEO_QUALITY_LINKMIC_MAIN_PUBLISHER;
            break;
          case Quality.LINKMIC_SUB:
            androidQuality = com_tencent_rtmp_TXLiveConstants
                .VIDEO_QUALITY_LINKMIC_SUB_PUBLISHER;
            break;
        }
        await _androidPusher.setVideoQuality(
          androidQuality,
          adjustBitrate,
          false,
        );
      },
      ios: (pool) async {
        TX_Enum_Type_VideoQuality iosQuality =
            TX_Enum_Type_VideoQuality.VIDEO_QUALITY_HIGH_DEFINITION;
        switch (quality) {
          case Quality.STANDARD:
            iosQuality =
                TX_Enum_Type_VideoQuality.VIDEO_QUALITY_STANDARD_DEFINITION;
            break;
          case Quality.HIGH:
            iosQuality =
                TX_Enum_Type_VideoQuality.VIDEO_QUALITY_HIGH_DEFINITION;
            break;
          case Quality.SUPER_HIGH:
            iosQuality =
                TX_Enum_Type_VideoQuality.VIDEO_QUALITY_SUPER_DEFINITION;
            break;
          case Quality.LINKMIC_MAIN:
            iosQuality =
                TX_Enum_Type_VideoQuality.VIDEO_QUALITY_LINKMIC_MAIN_PUBLISHER;
            break;
          case Quality.LINKMIC_SUB:
            iosQuality =
                TX_Enum_Type_VideoQuality.VIDEO_QUALITY_LINKMIC_SUB_PUBLISHER;
            break;
        }
        await _iosPusher.setVideoQuality_adjustBitrate_adjustResolution(
          iosQuality,
          adjustBitrate,
          false,
        );
      },
    );
  }

  /// 设置美颜效果
  ///
  /// [filter] 美颜算法
  /// [beautyLevel] 磨皮等级： 取值为 0-9.取值为 0 时代表关闭美颜效果.默认值: 0,即关闭美颜效果
  /// [whiteningLevel] 美白等级： 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.
  /// [ruddyLevel] 红润等级： 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.
  Future<void> setBeautyFilter(
    BeautyFilter filter, {
    int beautyLevel = 5,
    int whiteningLevel = 5,
    int ruddyLevel = 5,
  }) async {
    assert(filter != null);
    return platform(
      android: (pool) async {
        int androidFilter =
            com_tencent_rtmp_TXLiveConstants.BEAUTY_STYLE_SMOOTH;
        switch (filter) {
          case BeautyFilter.SMOOTH:
            androidFilter =
                com_tencent_rtmp_TXLiveConstants.BEAUTY_STYLE_SMOOTH;
            break;
          case BeautyFilter.NATURE:
            androidFilter =
                com_tencent_rtmp_TXLiveConstants.BEAUTY_STYLE_NATURE;
            break;
          case BeautyFilter.HAZY:
            androidFilter = com_tencent_rtmp_TXLiveConstants.BEAUTY_STYLE_HAZY;
            break;
        }
        await _androidPusher.setBeautyFilter(
          androidFilter,
          beautyLevel,
          whiteningLevel,
          ruddyLevel,
        );
      },
      ios: (pool) async {
        TX_Enum_Type_BeautyStyle iosFilter =
            TX_Enum_Type_BeautyStyle.BEAUTY_STYLE_SMOOTH;
        switch (filter) {
          case BeautyFilter.SMOOTH:
            iosFilter = TX_Enum_Type_BeautyStyle.BEAUTY_STYLE_SMOOTH;
            break;
          case BeautyFilter.NATURE:
            iosFilter = TX_Enum_Type_BeautyStyle.BEAUTY_STYLE_NATURE;
            break;
          case BeautyFilter.HAZY:
            iosFilter = TX_Enum_Type_BeautyStyle.BEAUTY_STYLE_PITU;
            break;
        }
        await _iosPusher
            .setBeautyStyle_beautyLevel_whitenessLevel_ruddinessLevel(
          iosFilter,
          beautyLevel.toDouble(),
          whiteningLevel.toDouble(),
          ruddyLevel.toDouble(),
        );
      },
    );
  }

  /// 色彩滤镜效果
  ///
  /// [specialRatio] 设定滤镜的浓度，设置的浓度越高，滤镜效果也就越明显
  Future<void> setFilter(
    AssetImage filterProvider,
    ImageConfiguration imageConfiguration, {
    double specialRatio = 0.5,
  }) async {
    final imageData = await filterProvider.toImageData(imageConfiguration);
    return platform(
      android: (pool) async {
        final bitmap = await android_graphics_Bitmap.create(imageData);
        await _androidPusher.setFilter(bitmap);
        await _androidPusher.setSpecialRatio(specialRatio);

        pool.add(bitmap);
      },
      ios: (pool) async {
        final bitmap = await UIImage.create(imageData);
        await _iosPusher.setFilter(bitmap);
        await _iosPusher.setSpecialRatio(specialRatio);

        pool.add(bitmap);
      },
    );
  }

  /// 调整摄像头的焦距
  ///
  /// 可以通过 TXLivePusher 的getMaxZoom()函数获取最大焦距，setZoom的取值范围即为 1 - 最大焦距
  Future<void> setZoom(int zoomLevel) async {
    return platform(
      android: (pool) => _androidPusher.setZoom(zoomLevel),
      ios: (pool) => _iosPusher.setZoom(zoomLevel.toDouble()),
    );
  }

  /// 设置曝光比例，取值范围从-1到1
  ///
  /// 负数表示调低曝光，-1是最小值，对应getMinExposureCompensation。正数表示调高曝光，1是最大值，对getMaxExposureCompensation。0表示不调整曝光，默认值为0
  Future<void> setExposureCompensation(int zoomLevel) async {
    return platform(
      android: (pool) => _androidPusher.setZoom(zoomLevel),
      ios: (pool) => _iosPusher.setZoom(zoomLevel.toDouble()),
    );
  }

  /// 观众端的镜像效果
  ///
  /// 调用 TXLivePusher 中的setMirror接口可以设置观众端的镜像效果。之所以说是观众端的镜像效果，
  /// 是因为当主播在使用前置摄像头直播时，自己看到的画面会被 SDK 默认反转，这时主播的体验跟自己照镜子时的体验是保持一致的。
  /// setMirror所影响的是观众端观看到的画面情况.
  Future<void> setMirror(bool mirror) async {
    return platform(
      android: (pool) => _androidPusher.setMirror(mirror),
      ios: (pool) => _iosPusher.setMirror(mirror),
    );
  }

  /// 横屏推流
  ///
  /// 大多数情况下，主播习惯以“竖屏持握”手机进行直播拍摄，观众端看到的也是竖屏分辨率的画面（例如 540 × 960 这样的分辨率）；
  /// 有时主播也会“横屏持握”手机，这时观众端期望能看到是横屏分辨率的画面（例如 960 × 540 这样的分辨率）
  ///
  /// TXLivePusher 默认推出的是竖屏分辨率的视频画面，如果希望推出横屏分辨率的画面，需要：
  ///   设置 TXLivePushConfig 中的setHomeOrientation改变观众端看到的视频画面的宽高比方向。
  ///   调用 TXLivePusher 中的setRenderRotation接口改变主播端的视频画面的渲染方向。
  Future<void> setRenderRotation(bool portrait) async {
    return platform(
      android: (pool) async {
        if (portrait) {
          await _androidConfig.setHomeOrientation(
              com_tencent_rtmp_TXLiveConstants.VIDEO_ANGLE_HOME_DOWN);
          await _androidPusher.setConfig(_androidConfig);
          await _androidPusher.setRenderRotation(0);
        } else {
          await _androidConfig.setHomeOrientation(
              com_tencent_rtmp_TXLiveConstants.VIDEO_ANGLE_HOME_RIGHT);
          await _androidPusher.setConfig(_androidConfig);
          // 因为采集旋转了，为了保证本地渲染是正的，则设置渲染角度为90度。
          await _androidPusher.setRenderRotation(90);
        }
      },
      ios: (pool) async {
        if (portrait) {
          await _iOSConfig.set_homeOrientation(
              TX_Enum_Type_HomeOrientation.HOME_ORIENTATION_DOWN.index);
          await _iosPusher.set_config(_iOSConfig);
          await _iosPusher.setRenderRotation(0);
        } else {
          await _iOSConfig.set_homeOrientation(
              TX_Enum_Type_HomeOrientation.HOME_ORIENTATION_RIGHT.index);
          await _iosPusher.set_config(_iOSConfig);
          await _iosPusher.setRenderRotation(90);
        }
      },
    );
  }

  /// 隐私模式（垫片推流）
  ///
  /// 有时候主播的一些动作不希望被观众看到，但直播过程中又不能下播，那就可以考虑进入隐私模式。
  /// 在隐私模式下，SDK 可以暂停采集主播手机的摄像头画面以及麦克风声音，并使用一张默认图片作为替代图像进行推流，也就是所谓的“垫片”。
  Future<void> setPauseConfig(
    int pauseTime,
    int pauseFps,
    ImageProvider image,
    ImageConfiguration imageConfiguration,
  ) async {
    final imageData = await image.toImageData(imageConfiguration);
    return platform(
      android: (pool) async {
        final bitmap = await android_graphics_Bitmap.create(imageData);

        await _androidConfig.setPauseImg__int__int(pauseTime, pauseFps);
        await _androidConfig.setPauseImg__android_graphics_Bitmap(bitmap);
        await _androidConfig.setPauseFlag(
          com_tencent_rtmp_TXLiveConstants.PAUSE_FLAG_PAUSE_AUDIO |
              com_tencent_rtmp_TXLiveConstants.PAUSE_FLAG_PAUSE_VIDEO,
        );

        await _androidPusher.setConfig(_androidConfig);

        pool.add(bitmap);
      },
      ios: (pool) async {
        await _iOSConfig.set_pauseTime(pauseTime);
        await _iOSConfig.set_pauseFps(pauseFps);

        final bitmap = await UIImage.create(imageData);
        await _iOSConfig.set_pauseImg(bitmap);

        await _iosPusher.set_config(_iOSConfig);

        pool.add(bitmap);
      },
    );
  }

  /// 设置混音效果
  Future<void> setReverbType(ReverbType type) async {
    return platform(
      android: (pool) async {
        int androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_0;
        switch (type) {
          case ReverbType.REVERB_TYPE_0:
            androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_0;
            break;
          case ReverbType.REVERB_TYPE_1:
            androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_1;
            break;
          case ReverbType.REVERB_TYPE_2:
            androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_2;
            break;
          case ReverbType.REVERB_TYPE_3:
            androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_3;
            break;
          case ReverbType.REVERB_TYPE_4:
            androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_4;
            break;
          case ReverbType.REVERB_TYPE_5:
            androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_5;
            break;
          case ReverbType.REVERB_TYPE_6:
            androidType = com_tencent_rtmp_TXLiveConstants.REVERB_TYPE_6;
            break;
          case ReverbType.REVERB_TYPE_7:
            debugPrint('android端暂无此类型混响效果');
            break;
        }
        await _androidPusher.setReverb(androidType);
      },
      ios: (pool) async {
        TXReverbType iosType = TXReverbType.REVERB_TYPE_0;
        switch (type) {
          case ReverbType.REVERB_TYPE_0:
            iosType = TXReverbType.REVERB_TYPE_0;
            break;
          case ReverbType.REVERB_TYPE_1:
            iosType = TXReverbType.REVERB_TYPE_1;
            break;
          case ReverbType.REVERB_TYPE_2:
            iosType = TXReverbType.REVERB_TYPE_2;
            break;
          case ReverbType.REVERB_TYPE_3:
            iosType = TXReverbType.REVERB_TYPE_3;
            break;
          case ReverbType.REVERB_TYPE_4:
            iosType = TXReverbType.REVERB_TYPE_4;
            break;
          case ReverbType.REVERB_TYPE_5:
            iosType = TXReverbType.REVERB_TYPE_5;
            break;
          case ReverbType.REVERB_TYPE_6:
            iosType = TXReverbType.REVERB_TYPE_6;
            break;
          case ReverbType.REVERB_TYPE_7:
            iosType = TXReverbType.REVERB_TYPE_7;
            break;
        }
        await _iosPusher.setReverbType(iosType);
      },
    );
  }

  /// 设置变调效果
  Future<void> setVoiceChangerType(VoiceChangerType type) async {
    return platform(
      android: (pool) async {
        int androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_0;
        switch (type) {
          case VoiceChangerType.VOICECHANGER_TYPE_0:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_0;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_1:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_1;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_2:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_2;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_3:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_3;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_4:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_4;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_5:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_5;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_6:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_6;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_7:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_7;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_8:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_8;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_9:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_9;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_10:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_10;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_11:
            androidType = com_tencent_rtmp_TXLiveConstants.VOICECHANGER_TYPE_11;
            break;
        }
        await _androidPusher.setVoiceChangerType(androidType);
      },
      ios: (pool) async {
        TXVoiceChangerType iosType = TXVoiceChangerType.VOICECHANGER_TYPE_0;
        switch (type) {
          case VoiceChangerType.VOICECHANGER_TYPE_0:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_0;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_1:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_1;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_2:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_2;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_3:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_3;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_4:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_4;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_5:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_5;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_6:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_6;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_7:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_7;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_8:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_8;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_9:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_9;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_10:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_10;
            break;
          case VoiceChangerType.VOICECHANGER_TYPE_11:
            iosType = TXVoiceChangerType.VOICECHANGER_TYPE_11;
            break;
        }
        await _iosPusher.setVoiceChangerType(iosType);
      },
    );
  }

  /// 设置 Logo 水印
  Future<void> setWatermark(
    ImageProvider watermark,
    ImageConfiguration imageConfiguration, {
    double x,
    double y,
    double width,
    double height,
  }) async {
    final imageData = await watermark.toImageData(imageConfiguration);
    return platform(
      android: (pool) async {
        final bitmap = await android_graphics_Bitmap.create(imageData);
        await _androidConfig
            .setWatermark__android_graphics_Bitmap__double__double__double(
          bitmap,
          x,
          y,
          width,
        );
        pool.add(bitmap);
      },
      ios: (pool) async {
        final bitmap = await UIImage.create(imageData);
        await _iOSConfig.set_watermark(bitmap);
        await _iOSConfig.set_watermarkNormalization(
          await CGRect.create(x, y, width, height),
        );
        pool.add(bitmap);
      },
    );
  }

  /// 开始本地录制
  Future<void> startRecord(String videoPath) async {
    return platform(
      android: (pool) => _androidPusher.startRecord(videoPath),
      ios: (pool) => _iosPusher.startRecord(videoPath),
    );
  }

  /// 停止本地录制
  Future<void> stopRecord() async {
    return platform(
      android: (pool) => _androidPusher.stopRecord(),
      ios: (pool) => _iosPusher.stopRecord(),
    );
  }

  /// 发送 SEI 消息
  Future<void> sendMessageEx(String message) async {
    return platform(
      android: (pool) => _androidPusher.sendMessageEx(utf8.encode(message)),
      ios: (pool) async {
        return _iosPusher.sendMessageEx(
          await NSData.createWithUint8List(utf8.encode(message)),
        );
      },
    );
  }
}

class _Holder {
  com_tencent_rtmp_TXLivePusher _androidPusher;
  TXLivePush _iosPusher;

  com_tencent_rtmp_TXLivePushConfig _androidConfig;
  TXLivePushConfig _iOSConfig;

  final _androidEventDelegate = _AndroidEventDelegate();
  final _iosEventDelegate = _IOSEventDelegate();
}
