// ignore_for_file: non_constant_identifier_names, camel_case_types, missing_return, unused_import, unused_local_variable, dead_code, unnecessary_cast
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 'player_delegates.dart';

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

  /// 创建一个播放器
  ///
  /// 直播和点播
  /// - 直播（LIVE）的视频源是主播实时推送的。因此，主播停止推送后，播放端的画面也会随即停止，而且由于是实时直播，所以播放器在播直播 URL 的时候是没有进度条的。
  /// - 点播（VOD）的视频源是云端的一个视频文件，只要未被从云端移除，视频就可以随时播放， 播放中您可以通过进度条控制播放位置，腾讯视频和优酷、土豆等视频网站上的视频观看就是典型的点播场景。
  ///
  /// 协议的支持
  /// - FLV 优点: 成熟度高、高并发无压力 缺点: 需集成 SDK 才能播放 播放延迟: 2s - 3s
  /// - RTMP 优点: 优质线路下理论延迟最低	缺点: 高并发情况下表现不佳	播放延迟: 1s - 3s
  /// - HLS（m3u8） 优点: 手机浏览器支持度高 缺点: 延迟非常高	播放延迟: 10s - 30s
  static Future<LivePlayer> create() async {
    return platform(
      android: (pool) async {
        final instance = LivePlayer._();

        final context = await android_app_Application.get();
        instance._androidPlayer = await com_tencent_rtmp_TXLivePlayer
            .create__android_content_Context(context);

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

        instance._iosPlayer = await TXLivePlayer.create__();

        return instance;
      },
    );
  }
}

mixin _Community on _Holder {
  /// 设置播放界面
  Future<void> setPlayerView(CloudVideoController playerView) async {
    return platform(
      android: (pool) async {
        await _androidPlayer.setPlayerView(playerView.playerView);
      },
      ios: (pool) async {
        // 其首个参数 frame 在 1.5.2 版本后已经被废弃
        final rect = await CGRect.create(0, 0, 0, 0);
        await _iosPlayer.setupVideoWidget_containView_insertIndex(
          rect,
          playerView.playerView,
          0,
        );
      },
    );
  }

  /// 开始播放
  Future<void> startPlay(String playUrl, {@required PlayType type}) async {
    final httpsUrl = Uri.parse(playUrl).scheme == 'http'
        ? playUrl.replaceFirst('http', 'https')
        : playUrl;
    return platform(
      android: (pool) async {
        int _type;
        switch (type) {
          case PlayType.RTMP:
            _type = com_tencent_rtmp_TXLivePlayer.PLAY_TYPE_LIVE_RTMP;
            break;
          case PlayType.FLV:
            _type = com_tencent_rtmp_TXLivePlayer.PLAY_TYPE_LIVE_FLV;
            break;
          case PlayType.RTMP_ACC:
            _type = com_tencent_rtmp_TXLivePlayer.PLAY_TYPE_LIVE_RTMP_ACC;
            break;
          case PlayType.HLS:
            _type = com_tencent_rtmp_TXLivePlayer.PLAY_TYPE_VOD_HLS;
            break;
        }
        final result = await _androidPlayer.startPlay(httpsUrl, _type);
        debugPrint('result: $result');
      },
      ios: (pool) async {
        TX_Enum_PlayType _type;
        switch (type) {
          case PlayType.RTMP:
            _type = TX_Enum_PlayType.PLAY_TYPE_LIVE_RTMP;
            break;
          case PlayType.FLV:
            _type = TX_Enum_PlayType.PLAY_TYPE_LIVE_FLV;
            break;
          case PlayType.RTMP_ACC:
            _type = TX_Enum_PlayType.PLAY_TYPE_LIVE_RTMP_ACC;
            break;
          case PlayType.HLS:
            _type = TX_Enum_PlayType.PLAY_TYPE_VOD_HLS;
            break;
        }
        final result = await _iosPlayer.startPlay_type(httpsUrl, _type);
        debugPrint('result: $result');
      },
    );
  }

  /// 恢复播放
  Future<void> resumePlay() async {
    return platform(
      android: (pool) => _androidPlayer.resume(),
      ios: (pool) => _iosPlayer.resume(),
    );
  }

  /// 恢复直播
  Future<int> resumeLive() async {
    return platform(
      android: (pool) => _androidPlayer.resumeLive(),
      ios: (pool) => _iosPlayer.resumeLive(),
    );
  }

  /// 是否在播放中
  Future<bool> isPlaying() async {
    return platform(
      android: (pool) => _androidPlayer.isPlaying(),
      ios: (pool) => _iosPlayer.isPlaying(),
    );
  }

  /// 暂停播放
  Future<void> pausePlay() async {
    return platform(
      android: (pool) => _androidPlayer.pause(),
      ios: (pool) => _iosPlayer.pause(),
    );
  }

  /// 停止播放
  Future<void> stopPlay() async {
    return platform(
      android: (pool) => _androidPlayer.stopPlay(true),
      ios: (pool) => _iosPlayer.stopPlay(),
    );
  }

  /// 事件处理
  Future<void> setOnEventListener({
    VoidCallback onWarningVideoDecodeFail,
    VoidCallback onWarningAudioDecodeFail,
    VoidCallback onWarningReconnect,
    VoidCallback onWarningRecvDataLag,
    VoidCallback onWarningVideoPlayLag,
    VoidCallback onWarningHwAccelerationFail,
    VoidCallback onWarningVideoDiscontinuity,
    VoidCallback onWarningDNSFail,
    VoidCallback onWarningServerConnFail,
    VoidCallback onWarningShakeFail,
    VoidCallback onEventRcvFirstIFrame,
    VoidCallback onEventPlayBegin,
    VoidCallback onEventPlayEnd,
  }) async {
    return platform(
      android: (pool) async {
        await _androidPlayer.setPlayListener(
          _androidEventDelegate
            .._onWarningVideoDecodeFail = onWarningVideoDecodeFail
            .._onWarningAudioDecodeFail = onWarningAudioDecodeFail
            .._onWarningReconnect = onWarningReconnect
            .._onWarningRecvDataLag = onWarningRecvDataLag
            .._onWarningVideoPlayLag = onWarningVideoPlayLag
            .._onWarningHwAccelerationFail = onWarningHwAccelerationFail
            .._onWarningVideoDiscontinuity = onWarningVideoDiscontinuity
            .._onWarningDNSFail = onWarningDNSFail
            .._onWarningServerConnFail = onWarningServerConnFail
            .._onWarningShakeFail = onWarningShakeFail
            .._onEventRcvFirstIFrame = onEventRcvFirstIFrame
            .._onEventPlayBegin = onEventPlayBegin
            .._onEventPlayEnd = onEventPlayEnd,
        );
      },
      ios: (pool) async {
        await _iosPlayer.set_delegate(
          _iosEventDelegate
            .._onWarningVideoDecodeFail = onWarningVideoDecodeFail
            .._onWarningAudioDecodeFail = onWarningAudioDecodeFail
            .._onWarningReconnect = onWarningReconnect
            .._onWarningRecvDataLag = onWarningRecvDataLag
            .._onWarningVideoPlayLag = onWarningVideoPlayLag
            .._onWarningHwAccelerationFail = onWarningHwAccelerationFail
            .._onWarningVideoDiscontinuity = onWarningVideoDiscontinuity
            .._onWarningDNSFail = onWarningDNSFail
            .._onWarningServerConnFail = onWarningServerConnFail
            .._onWarningShakeFail = onWarningShakeFail
            .._onEventRcvFirstIFrame = onEventRcvFirstIFrame
            .._onEventPlayBegin = onEventPlayBegin
            .._onEventPlayEnd = onEventPlayEnd,
        );
      },
    );
  }

  Future<void> dispose() async {
    return platform(
      android: (pool) async {
        await _androidPlayer.stopPlay(true);
        await _androidPlayer.release__();
      },
      ios: (pool) async {
        await _iosPlayer.removeVideoWidget();
        await _iosPlayer.release__();
      },
    );
  }
}

mixin _Pro on _Holder {
  /// 清晰度无缝切换
  ///
  /// 日常使用中，网络情况在不断发生变化。在网络较差的情况下，最好适度降低画质，以减少卡顿；反之，网速比较好，可以提高观看画质。
  /// 传统切流方式一般是重新播放，会导致切换前后画面衔接不上、黑屏、卡顿等问题。使用无缝切换方案，在不中断直播的情况下，能直接切到另条流上。
  /// 清晰度切换在直播开始后，任意时间都可以调用。
  Future<void> switchStream(String newStream) async {
    return platform(
      android: (pool) => _androidPlayer.switchStream(newStream),
      ios: (pool) => _iosPlayer.switchStream(newStream),
    );
  }

  /// 画面调整
  ///
  /// 铺满or适应
  Future<void> setRenderMode(RenderMode renderMode) async {
    return platform(
      android: (pool) async {
        int _renderMode;
        switch (renderMode) {
          case RenderMode.FULL_SCREEN:
            _renderMode =
                com_tencent_rtmp_TXLiveConstants.RENDER_MODE_FULL_FILL_SCREEN;
            break;
          case RenderMode.ADJUST_RESOLUTION:
            _renderMode =
                com_tencent_rtmp_TXLiveConstants.RENDER_MODE_ADJUST_RESOLUTION;
            break;
        }
        await _androidPlayer.setRenderMode(_renderMode);
      },
      ios: (pool) async {
        TX_Enum_Type_RenderMode _renderMode;
        switch (renderMode) {
          case RenderMode.FULL_SCREEN:
            _renderMode = TX_Enum_Type_RenderMode.RENDER_MODE_FILL_SCREEN;
            break;
          case RenderMode.ADJUST_RESOLUTION:
            _renderMode = TX_Enum_Type_RenderMode.RENDER_MODE_FILL_EDGE;
            break;
        }
        await _iosPlayer.setRenderMode(_renderMode);
      },
    );
  }
}

class _Holder {
  com_tencent_rtmp_TXLivePlayer _androidPlayer;
  TXLivePlayer _iosPlayer;

  com_tencent_rtmp_TXLivePlayConfig _androidConfig;
  TXLivePlayConfig _iOSConfig;

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