import 'package:fis_common/logger/logger.dart';
import 'package:fis_lib_media_rt/base/room.dart';
import 'package:fis_lib_media_rt/implementations/nt_rtmp/members.dart';
import 'package:fis_lib_media_rt/implementations/nt_rtmp/models.dart';
import 'package:fis_lib_media_rt/interface/member.dart';
import 'package:fis_lib_media_rt/interface/publisher.dart';

import 'package:fis_lib_media_rt/interface/player.dart';
import 'package:flutter/foundation.dart';

import 'native_share.dart';
import 'player.dart';
import 'publisher.dart';
import 'rtc_adapter.dart';
import 'values.dart';

class NTRtmpRoom extends BaseRoom {
  NTPlayer? _player;
  NTPublisher? _publisher;

  NTRtmpRoom() {
    NTRtmp2RtcAdapter.adapter.room = this;
    _listenAdapter();
  }

  @override
  Future<void> enter() async {
    try {
      NTRtmp2RtcAdapter.adapter.room = this;

      if (kIsWeb) {
        await Future.delayed(const Duration(milliseconds: 100));
      } else {
        await NTNativeShare.instance.enterRoom();
      }
      entered.emit(this, null);
    } catch (e) {
      logger.e("$TAG - Enter room error", e);
    }
  }

  @override
  Future<void> exit() async {
    try {
      NTRtmp2RtcAdapter.adapter.room = null;
      NTRtmp2RtcAdapter.adapter.localMemberInfo = null;

      if (kIsWeb) {
        await Future.delayed(const Duration(milliseconds: 100));
      } else {
        await NTNativeShare.instance.exitRoom();
      }
      exited.emit(this, null);
    } catch (e) {
      logger.e("$TAG - Exit room error", e);
    }
  }

  @override
  Future<void> captureVideoFrame(String? userId, int streamType, String path) {
    // TODO: implement captureVideoFrame
    throw UnimplementedError();
  }

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

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

  @override
  void loadLocalMember(ILocalMemberParams params) {
    if (NTRtmp2RtcAdapter.adapter.localMemberInfo != null) {
      localMember = NTLocalMember(
        params: params,
        memberInfo: NTRtmp2RtcAdapter.adapter.localMemberInfo!,
      );
    }
  }

  void _listenAdapter() {
    final adapter = NTRtmp2RtcAdapter.adapter;
    adapter.remoteMemberJoineEvent.addListener(_onRemoteMemberJoin);
    adapter.remoteMemberLeaveEvent.addListener(_onRemoteMemberLeave);
  }

  void _unlistenAdapter() {
    final adapter = NTRtmp2RtcAdapter.adapter;
    adapter.remoteMemberJoineEvent.removeListener(_onRemoteMemberJoin);
    adapter.remoteMemberLeaveEvent.removeListener(_onRemoteMemberLeave);
  }

  void _onRemoteMemberJoin(_, RtmpMemberInfo e) {
    final userId = e.id;
    logger.i("$TAG - Remote user-$userId join");
    final member = NTRemoteMember(userId: userId, memberInfo: e);
    if (addMember(member)) {
      memberJoined.emit(this, member);
    }
  }

  void _onRemoteMemberLeave(_, String e) {
    logger.i("$TAG - Remote user-$e leave");
    for (var i = 0; i < remoteMembers.length; i++) {
      final member = remoteMembers[i] as NTRemoteMember;
      if (member.userId == e) {
        removeMemberAt(i);
        memberLeaved.emit(this, member);
        break;
      }
    }
  }

  @override
  Future<void> startScreenCapture(String userId, String userSign) async {
    // TODO: implement startScreenCapture
    throw UnimplementedError();
  }

  @override
  Future<void> stopScreenCapture() {
    // TODO: implement stopScreenCapture
    throw UnimplementedError();
  }
}
