import 'package:fis_lib_media_rt/base/member.dart';
import 'package:fis_lib_media_rt/implementations/trtc/publisher.dart';
import 'package:fis_lib_media_rt/interface/publisher.dart';
import 'package:fis_lib_media_rt/interface/player.dart';
import 'package:tencent_trtc_cloud/trtc_cloud.dart';
import 'package:tencent_trtc_cloud/trtc_cloud_def.dart';
import 'package:tencent_trtc_cloud/trtc_cloud_listener.dart';

import '../../base/player.dart';
import '../../base/room.dart';
import '../../config.dart';
import 'channel.dart';
import 'client_getter_mixin.dart';
import 'events.dart';
import 'member.dart';
import 'player.dart';

class TrtcRoom extends BaseRoom {
  TRTCCloud? _client;
  TrtcPublisher? _publisher;
  TrtcPlayer? _player;

  late TrtcEvents events;

  TrtcRoom({required super.id});

  TRTCCloud get trtcClient => _client!;

  @override
  Future<void> enter() async {
    await _initRoom();

    try {
      await _client!.enterRoom(
        TRTCParams(
          sdkAppId: FRTMediaConfig.trtc.appid,
          userId: localMember.params.userId!,
          userSig: localMember.params.userSig!,
          role: TRTCCloudDef.TRTCRoleAnchor,
          roomId: int.parse(roomId),
        ),
        TRTCCloudDef.TRTC_APP_SCENE_LIVE,
      );
      Future.delayed(const Duration(milliseconds: 100), () {
        entered.emit(this, null);
      });
    } catch (e) {
      // TODO: log
    }
  }

  @override
  Future<void> exit() async {
    try {
      events.dispose();
      // await _client!.exitRoom();
      _client = null;
      await TRTCCloud.destroySharedInstance();
      Future.delayed(const Duration(milliseconds: 100), () {
        exited.emit(this, null);
      });
    } catch (e) {
      // TODO: log
    }
  }

  @override
  Future<void> captureVideoFrame(
    String? userId,
    int streamType,
    String path,
  ) async {
    try {
      await _client!.snapshotVideo(
        userId,
        streamType,
        path,
      );
    } catch (e) {
      // TODO: log
    }
  }

  Future<void> _initRoom() async {
    if (_client != null) return;

    try {
      _client = await TRTCCloud.sharedInstance();
      TrtcClientGetterMixin.sharedInstance = _client!;
      events = TrtcEvents(room: this);
      _listenEvents();
      _client!.setConsoleEnabled(false); //TODO: Web下disable竟然无效
      _client!.setLogLevel(4); // Error only
    } catch (e) {
      // TODO: log
    }
  }

  void _listenEvents() {
    events.on(TRTCCloudListener.onError, _onError);
    events.on(TRTCCloudListener.onWarning, _onWarning);
    events.on(TRTCCloudListener.onRemoteUserEnterRoom, _onRemoteUserEnter);
    events.on(TRTCCloudListener.onRemoteUserLeaveRoom, _onRemoteUserLeave);
    events.on(TRTCCloudListener.onFirstVideoFrame, _onFirstVideoFrame);
    events.on(TRTCCloudListener.onUserSubStreamAvailable, _subStreamAvailable);
  }

  void _onError(dynamic param) {
    print(param); // TODO:
  }

  void _onWarning(dynamic param) {
    // 被踢出房间
    // exit(); //TODO:
  }

  void _onRemoteUserEnter(dynamic param) {
    //TODO: remove print
    print(
        "!!!!!!!_onRemoteUserEnter local-${localMember.params.userId} remote-$param");
    final member = TrtcRemoteMember(userId: param);
    addMember(member);
    memberJoined.emit(this, member);
  }

  void _onRemoteUserLeave(dynamic param) {
    //TODO: remove print
    String userId = param['userId'];
    print(
        "!!!!!!!_onRemoteUserLeave local-${localMember.params.userId} remote-$userId");
    for (var i = 0; i < remoteMembers.length; i++) {
      final member = remoteMembers[i] as TrtcRemoteMember;
      if (member.userId == userId) {
        removeMemberAt(i);
        memberLeaved.emit(this, member);
        break;
      }
    }
  }

  void _onFirstVideoFrame(dynamic param) {
    print("🎉🎉🎉 onFirstVideoFrame");
    //TODO: remove print
    String userId = param['userId'];
    double width = param['width'];
    double height = param['height'];
    // 获取宽高
    print(
        "🎉🎉🎉 onFirstVideoFrame get remote-$userId width-$width height-$height");
  }

  @override
  IPlayer createPlayer() {
    _player ??= TrtcPlayer(room: this);
    return _player!;
  }

  @override
  IPublisher createPublisher() {
    _publisher ??= TrtcPublisher(room: this);
    return _publisher!;
  }

  @override
  Future<void> startScreenCapture(String userId, String userSign) async {
    await _client!.startScreenCapture(1, TRTCVideoEncParam(),
        shareUserId: userId, shareUserSig: userSign);
  }

  @override
  Future<void> stopScreenCapture() async {
    await _client!.stopScreenCapture();
  }

  void _subStreamAvailable(dynamic param) {
    print(
        "??????_subStreamAvailable local-${localMember.params.userId} remote-$param");
    final member = TrtcRemoteMember(userId: param);
    addMember(member);
    memberJoined.emit(this, member);
  }
}
