import 'package:fis_lib_media_rt/implementations/trtc/room.dart';
import 'package:tencent_trtc_cloud/trtc_cloud_listener.dart';

typedef TrtcEventCallback = void Function(dynamic param);

class TrtcEvents {
  final Map<TRTCCloudListener, Set<TrtcEventCallback>> _callbackMap = {};
  final Map<TRTCCloudListener, Set<TrtcEventCallback>> _callbackOnceMap = {};

  final TrtcRoom room;

  TrtcEvents({required this.room}) {
    room.trtcClient.registerListener(_onEvents);
  }

  void once(TRTCCloudListener type, TrtcEventCallback callback) {
    final s = _findOnceCbSet(type);
    s.add(callback);
  }

  void on(TRTCCloudListener type, TrtcEventCallback callback) {
    final s = _findCbSet(type);
    s.add(callback);
  }

  void off(TRTCCloudListener type, TrtcEventCallback callback) {
    final s = _findCbSet(type);
    s.remove(callback);
  }

  void dispose() {
    room.trtcClient.unRegisterListener(_onEvents);
  }

  void _onEvents(TRTCCloudListener type, dynamic param) {
    final s = _findCbSet(type);
    for (var cb in s) {
      cb.call(param);
    }
    final os = _findOnceCbSet(type);
    for (var cb in os) {
      cb.call(param);
      Future.delayed(const Duration(milliseconds: 10), () {
        os.remove(cb);
      });
    }
  }

  Set<TrtcEventCallback> _findCbSet(TRTCCloudListener type) {
    var matchSet = _callbackMap[type];
    if (matchSet == null) {
      matchSet = {};
      _callbackMap[type] = matchSet;
    }
    return matchSet;
  }

  Set<TrtcEventCallback> _findOnceCbSet(TRTCCloudListener type) {
    var matchSet = _callbackOnceMap[type];
    if (matchSet == null) {
      matchSet = {};
      _callbackOnceMap[type] = matchSet;
    }
    return matchSet;
  }
}
