import 'dart:convert';

import 'package:fis_common/event/event_type.dart';
import 'package:fis_common/helpers/encrypt.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/web_parameter_helpler.dart';
import 'package:flyinsono/managers/interfaces/entities/patient_Info.dart';
import 'package:flyinsono/managers/base_manager.dart';
import 'package:flyinsono/managers/interfaces/entities/consultation_member.dart';
import 'package:flyinsono/notifications/handlers/consulation/accept_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/answer_timeout_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/cancel_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/cancel_inviting_in_live_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/change_consultation.dart';
import 'package:flyinsono/notifications/handlers/consulation/close_consultation_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/close_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/device_parameters_notification.dart';
import 'package:flyinsono/notifications/handlers/consulation/emergency_call_failed_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/emergency_call_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/invite_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/invite_in_live_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/join_handlers.dart';
import 'package:flyinsono/notifications/handlers/consulation/join_in_consultation.dart';
import 'package:flyinsono/notifications/handlers/consulation/leave_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/member_heart_rate_join_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/member_leave_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/mute_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/neterror_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/reject_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/reject_invite_live_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/send_interactive_board_data_handler.dart';
import 'package:flyinsono/notifications/handlers/consulation/switch_video_play.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';
import '../notifications/handlers/consulation/cancel_inviting_in_live_course_notification.dart';
import 'interfaces/entities/invitee_consulation_info.dart';
import 'interfaces/entities/live_consultation.dart';
import 'interfaces/live_consultation.dart';
import 'interfaces/rtmp_mock_rtc.dart';
part 'live_consultation_after_manager.dart';

class LiveConsultationManager extends BaseManager
    implements ILiveConsultationManager {
  ///缓存会诊信息
  LiveConsultation? liveConsultation;

  /// 白板数据接收
  final FEventHandler<String> onWhiteboardDataReceive = FEventHandler<String>();

  ///开始会诊通知事件 11
  final FEventHandler<LiveConsultation> onInviteLiveConsultation =
      FEventHandler<LiveConsultation>();

  ///会诊过程中邀请成员的通知(通知被邀请者) 8
  final FEventHandler<LiveConsultation> onInviteeInLiveConsultation =
      FEventHandler<LiveConsultation>();

  ///取消会诊过程中邀请成员的通知(通知被邀请者) 7
  final FEventHandler<LiveConsultation> onCancelInvitingConsultation =
      FEventHandler<LiveConsultation>();

  ///邀请者接受会诊通知事件（通知发起者）12
  final FEventHandler<LiveConsultation> onAcceptConsultation =
      FEventHandler<LiveConsultation>();

  ///邀请者拒绝会诊事件（通知发起者） 13
  final FEventHandler<LiveConsultation> onRejectConsultation =
      FEventHandler<LiveConsultation>();

  ///邀请者取消接听会诊事件（通知发起者） 7
  final FEventHandler<LiveConsultation> onCancelConsultation =
      FEventHandler<LiveConsultation>();

  ///关闭会诊事件（通知所有成员） 16
  final FEventHandler<LiveConsultation> onCloseConsultation =
      FEventHandler<LiveConsultation>();

  ///成员加入会诊事件（通知所有成员）-
  final FEventHandler<LiveConsultation> onAcceptLiveConsultation =
      FEventHandler<LiveConsultation>();

  ///成员加入会诊事件（通知所有成员）
  final FEventHandler<LiveConsultation> onJoinConsultation =
      FEventHandler<LiveConsultation>();

  ///成员加入会诊事件（通知所有成员） 被邀请者进入房间通知
  final FEventHandler<LiveConsultation> onJoinInConsultation =
      FEventHandler<LiveConsultation>();

  ///成员离开会诊事件（通知所有成员）19
  final FEventHandler<LiveConsultation> onLeaveConsultation =
      FEventHandler<LiveConsultation>();

  ///某个成员网络不佳通知事件（通知所有成员） 18
  final FEventHandler<LiveConsultation> onNetworkErrConsultation =
      FEventHandler<LiveConsultation>();

  ///缓存未处理的设备参数通知
  DeviceParametersNotification? cacheDeviceParametersNotification;

  /// 设备探头应用和参数信息通知事件 35
  final FEventHandler<DeviceParametersNotification>
      onDeviceParametersNotification =
      FEventHandler<DeviceParametersNotification>();

  /// 68 取消呼叫 to 客户端
  final FEventHandler<CancelInvitingInLiveCourseNotification>
      onCancelInvitingInLiveCourseNotification =
      FEventHandler<CancelInvitingInLiveCourseNotification>();

  ///会诊提醒通知
  final FEventHandler<InviteeConsulationInfo> onRemindConsultation =
      FEventHandler<InviteeConsulationInfo>();

  ///邀请者拒绝会诊事件（通知发起者）
  final FEventHandler<InviteeConsulationInfo> onRejectApplayConsultation =
      FEventHandler<InviteeConsulationInfo>();

  ///批准申请会诊通知
  final FEventHandler<InviteeConsulationInfo> onApprovalApplayConsultation =
      FEventHandler<InviteeConsulationInfo>();

  ///申请会诊通知
  final FEventHandler<InviteeConsulationInfo> onApplayConsultation =
      FEventHandler<InviteeConsulationInfo>();

  ///受邀请人通知（通知受邀请人）
  final FEventHandler<InviteeConsulationInfo> onInviteeConsultation =
      FEventHandler<InviteeConsulationInfo>();

  ///受邀请人同意通知（通知发起邀请的人）
  final FEventHandler<InviteeConsulationInfo> onInviteeApproveConsultation =
      FEventHandler<InviteeConsulationInfo>();

  ///受邀请人拒绝通知（通知发起邀请的人）
  final FEventHandler<InviteeConsulationInfo> onInviteeRejectConsultation =
      FEventHandler<InviteeConsulationInfo>();

  ///开启会诊事件
  final FEventHandler<LiveConsultation> onStartLiveConsultation =
      FEventHandler<LiveConsultation>();

  //成员静音通知
  final FEventHandler<ConsultationMember> onMemberMute =
      FEventHandler<ConsultationMember>();

  //成员静音通知
  final FEventHandler<ConsultationMember> onSwitchVideoPlay =
      FEventHandler<ConsultationMember>();

  ///会诊间改变
  final FEventHandler<LiveConsultation> onChangeConsultation =
      FEventHandler<LiveConsultation>();

  ///主动退出会诊间事件
  final FEventHandler<bool> onExitConsultation = FEventHandler<bool>();

  ///会诊间改变，成员不在新的会诊间，需退出
  final FEventHandler<LiveConsultation> onCloseConsultationDueToChange =
      FEventHandler<LiveConsultation>();

  LiveConsultationManager() {
    // 互动白板数据通知
    var sendInteractiveBoardDataHandler =
        Get.find<SendInteractiveBoardDataHandler>();
    // 取消会诊过程中邀请成员的通知 7
    var cancelInvitingHandler =
        Get.find<CancelInvitingInLiveConsultationHandler>();
    //会诊过程中邀请成员的通知  8
    var inviteInLiveConsulationHandler =
        Get.find<InviteInLiveConsultationHandler>();
    //开始会诊的通知  11
    var inviteLiveConsultHandler =
        Get.find<InviteLiveConsultationNotificationHandler>();
    //接受会诊的通知 12
    var acceptLiveConsultationHandler =
        Get.find<AcceptLiveConsultationNotificationHandler>();

    //拒绝会诊的通知 13
    var rejectLiveConsultationHandler =
        Get.find<RejectLiveConsultationHandler>();
    //拒绝会诊的通知 21
    var rejectInviteLiveConsultationHandler =
        Get.find<RejectInviteLiveConsultationHandler>();
    //取消会诊通知 15
    var cancelLiveConsulation =
        Get.find<CancelLiveConsultationNotificationHandler>();

    //关闭会诊通知  16
    var closeLiveConsultHandler =
        Get.find<CloseLiveConsultationNotificationHandler>();
    // 进入会诊通知 17
    var joinLiveConsultHandler =
        Get.find<JoinLiveConsultationNotificationHandler>();
    //网络质量不佳会诊通知  18
    var networkErrConsultationHandler =
        Get.find<NetworkErrConsultationNotificationHandler>();
    //离开会诊通知  19
    var leaveConsultationHandler =
        Get.find<LeaveConsultationNotificationHandler>();
    var joinInHandler =
        Get.find<JoinInLiveConsultationNotificationHandler>(); //20 邀请的成员加入会诊
    //成员静音通知 27
    var muteLiveConsultationHandler = Get.find<MuteLiveConsultationHandler>();
    //成员启用或关闭摄像头通知 28
    var switchVideoPlayConsultationHandler =
        Get.find<SwitchVideoPlayConsultationHandler>();
    var heartRateJoinConsultationHandler =
        Get.find<HeartRateJoinConsultationHandler>();
    //成员心跳断开离开 30
    var heartRateLeaveConsultationHandler =
        Get.find<HeartRateLeaveConsultationHandler>();
    var changeConsultationNotification =
        Get.find<ChangeConsultationNotificationHandler>();
    var closeConsultationDueToChangeNotificationHandler =
        Get.find<CloseConsultationDueToChangeNotificationHandler>();

    var deviceParametersNotificationHandler =
        Get.find<DeviceParametersNotificationHandler>();

    ///急诊呼叫专家通知 37
    var emergencyCallNotificationHandler =
        Get.find<EmergencyCallNotificationHandler>();
    var emergencyCallFailedNotificationHandler =
        Get.find<EmergencyCallFailedNotificationHandler>();

    ///呼叫超时
    var consultationAnswerTimeoutHandler =
        Get.find<ConsultationAnswerTimeoutHandler>();

    /// 取消呼叫 to 客户端 68
    var cancelInvitingInLiveCourseNotificationHandler =
        Get.find<CancelInvitingInLiveCourseNotificationHandler>();

    sendInteractiveBoardDataHandler
        .subscribe(_onSendInteractiveBoardDataHandler);
    cancelLiveConsulation.subscribe(_onCancelLiveConsulation);
    rejectLiveConsultationHandler.subscribe(_onRejectLiveConsultationHandler);
    rejectInviteLiveConsultationHandler
        .subscribe(_onRejectInviteLiveConsultationHandler);
    acceptLiveConsultationHandler.subscribe(_onAcceptLiveConsultationHandler);
    inviteInLiveConsulationHandler.subscribe(_onInviteInLiveHandler);
    cancelInvitingHandler.subscribe(_onCancelInvitingHandler);
    inviteLiveConsultHandler.subscribe(_onInviteLiveConsultHandler);
    closeLiveConsultHandler.subscribe(_onCloseLiveConsultHandler);
    joinLiveConsultHandler.subscribe(_onJoinLiveConsultHandler);
    leaveConsultationHandler.subscribe(_onleaveConsultationHandler);
    networkErrConsultationHandler.subscribe(_onNetworkErrConsultationHandler);
    deviceParametersNotificationHandler
        .subscribe(_onDeviceParametersNotificationHandler);
    cancelInvitingInLiveCourseNotificationHandler
        .subscribe(_onCancelInvitingInLiveCourseNotificationHandler);
    muteLiveConsultationHandler.subscribe(_onMuteLiveConsultationHandler);
    heartRateJoinConsultationHandler
        .subscribe(_onHeartRateJoinConsultationHandler);
    switchVideoPlayConsultationHandler
        .subscribe(_onSwitchVideoPlayConsultationHandler);
    heartRateLeaveConsultationHandler
        .subscribe(_onHeartRateLeaveConsultationHandler);
    joinInHandler.subscribe(_onJoinInLiveConsultationHandler);
    changeConsultationNotification.subscribe(_onChangeConsultationHandler);
    closeConsultationDueToChangeNotificationHandler
        .subscribe(_onCloseConsultationDueToChangeHandler);
    emergencyCallNotificationHandler
        .subscribe(_onEmergencyCallNotificationHandler);
    emergencyCallFailedNotificationHandler.subscribe(_onEmergencyCallFailed);
    consultationAnswerTimeoutHandler.subscribe(_onAnswerTimeoutHandler);
  }

  @override
  Future<LiveConsultation> initiateLiveConsultationAsync(
      String consultationCode,
      {bool checkOnly = false}) async {
    final result = await rpc.liveConsultation.initiateLiveConsultationAsync(
      InitiateLiveConsultationRequest(
        token: Store.user.token,
        consultationCode: consultationCode,
        checkOnly: checkOnly,
      ),
    );

    Get.find<IRtmpMockRtcManager>().storeOriginData(result.memberLiveDatas);

    var liveConsultation = LiveConsultation(
      consultationCode: result.consultationCode,
      initiatorCode: result.initiatorCode,
      roomNo: result.roomNo,
      appId: result.appId,
      userSign: result.userSign,
    );
    liveConsultation.consultationMemberConvert(result.memberLiveDatas ?? []);
    this.liveConsultation = liveConsultation;
    this.onStartLiveConsultation.emit(this, liveConsultation);
    return liveConsultation;
  }

  @override
  Future<LiveConsultation> acceptLiveConsultationAsync(String consultationCode,
      {bool checkOnly = false}) async {
    var result = await rpc.liveConsultation.acceptLiveConsultationAsync(
      AcceptLiveConsultationRequest(
        token: Store.user.token,
        consultationCode: consultationCode,
        checkOnly: checkOnly,
      ),
    );

    //_mockDevice(result.memberLiveDatas); //TODO[melon]: Mock merge

    Get.find<IRtmpMockRtcManager>().storeOriginData(result.memberLiveDatas);

    var liveConsultation = LiveConsultation(
      consultationCode: result.consultationCode,
      userCode: result.userCode,
      roomNo: result.roomNo,
      appId: result.appId,
      userSign: result.userSign,
      interactiveBoardDatas: result.interactiveBoardDatas,
    );
    liveConsultation.consultationMemberConvert(result.memberLiveDatas ?? []);
    this..onAcceptLiveConsultation.emit(this, liveConsultation);
    return liveConsultation;
  }

  /// 查询会诊详情
  @override
  Future<ConsultationDetailDTO?> findConsultationDetailAsync(
      String consultationCode) async {
    try {
      if (Store.user.token.isEmpty &&
          ParameterHelper.parasmeters.isNotEmpty &&
          ParameterHelper.parasmeters.containsKey('token')) {
        Store.user.setToken(ParameterHelper.parasmeters['token'] ?? '');
      }
      final result = await rpc.liveConsultation.findConsultationDetailAsync(
        FindConsultationDetailRequest(
          token: Store.user.token,
          consultationCode: consultationCode,
        ),
      );
      return result;
    } catch (e) {
      logger.i("parasmeters:${ParameterHelper.parasmeters}");
      logger.e("findConsultationDetailAsync exception:", e);
    }
    return null;
  }

  Future<QueryEmergencyDataResult> queryEmergencyData() async {
    return await rpc.liveConsultation.queryEmergencyDataAsync(
      TokenRequest(token: token),
    );
  }

  ///进入会诊
  @override
  Future<LiveConsultation> joinInLiveConsultationAsync(String consultationCode,
      {bool checkOnly = false}) async {
    final result = await rpc.liveConsultation.joinInLiveConsultationAsync(
      JoinLiveConsultationRequest(
        token: Store.user.token,
        consultationCode: consultationCode,
        checkOnly: checkOnly,
      ),
    );

    //_mockDevice(result.memberLiveDatas); //TODO[melon]: Mock merge

    Get.find<IRtmpMockRtcManager>().storeOriginData(result.memberLiveDatas);

    var liveConsultation = LiveConsultation(
      consultationCode: result.consultationCode,
      userCode: result.userCode,
      roomNo: result.roomNo,
      appId: result.appId,
      userSign: result.userSign,
      interactiveBoardDatas: result.interactiveBoardDatas,
    );
    liveConsultation.consultationMemberConvert(result.memberLiveDatas ?? []);
    return liveConsultation;
  }

  @override
  Future<RejectLiveConsultationResult> rejectLiveConsultationAsync(
      String consultationCode) {
    return rpc.liveConsultation
        .rejectLiveConsultationAsync(RejectLiveConsultationRequest(
      consultationCode: consultationCode,
      token: Store.user.token,
    ));
  }

  ///会诊过程中邀请其他成员
  @override
  Future<InviteInLiveConsultationResult> inviteInLiveConsultationAsync(
      String consultationCode, List<String> inviteCodes, int roomNo) {
    return rpc.liveConsultation
        .inviteInLiveConsultationAsync(InviteInLiveConsultationRequest(
      token: Store.user.token,
      consultationCode: consultationCode,
      inviteCodes: inviteCodes,
      roomNo: roomNo,
    ));
  }

  ///设置开启或关闭静音
  @override
  Future<MuteLiveConsultationResult> muteLiveConsultationAsync(
      String consultationCode, bool isMute) async {
    return await rpc.liveConsultation
        .muteLiveConsultationAsync(MuteLiveConsultationRequest(
      consultationCode: consultationCode,
      token: Store.user.token,
      mute: isMute,
    ));
  }

  ///设置开启或关闭视频
  @override
  Future<SwitchLiveConsultationVideoResult> switchLiveConsultationVideoAsync(
      String consultationCode, bool isOpen) async {
    return rpc.liveConsultation
        .switchLiveConsultationVideoAsync(SwitchLiveConsultationVideoRequest(
      token: Store.user.token,
      consultationCode: consultationCode,
      opened: isOpen,
    ));
  }

  ///离开房间
  @override
  Future<LeaveLiveConsultationResult> leaveLiveConsultationAsync(
      String consultationCode) async {
    try {
      return rpc.liveConsultation.leaveLiveConsultationAsync(
        LeaveLiveConsultationRequest(
          consultationCode: consultationCode,
          token: Store.user.token,
        ),
      );
    } catch (e) {
      logger.e('LiveConsultationManager leaveLiveConsultationAsync', e);
    }
    return LeaveLiveConsultationResult();
  }

  ///取消会诊
  @override
  Future<CancelLiveConsultationResult> cancelLiveConsultationAsync(
      String consultationCode) {
    return rpc.liveConsultation
        .cancelLiveConsultationAsync(CancelLiveConsultationRequest(
      consultationCode: consultationCode,
      token: Store.user.token,
    ));
  }

  ///取消会诊过程邀请中的成员
  @override
  Future<CancelInvitingInLiveConsultationResult>
      cancelInvitingInLiveConsultationAsync(
          String consultationCode, List<String> inviteCodes) {
    return rpc.liveConsultation.cancelInvitingInLiveConsultationAsync(
        CancelInvitingInLiveConsultationRequest(
      consultationCode: consultationCode,
      inviteCodes: inviteCodes,
      token: Store.user.token,
    ));
  }

  @override
  Future<LiveConsultationHeartRateResult> consultationHeartRateSendOnce(
      String consultationCode) async {
    return await rpc.liveConsultation.heartRateAsync(
      LiveConsultationHeartRateRequest(
        token: Store.user.token,
        consultationCode: consultationCode,
      ),
    );
  }

  /// 远程调参
  @override
  Future<bool> controlParameterAsync(
    String consultationCode,
    List<AdditionParameterDTO> parameters,
    ControlDeviceParameterEnum controlType,
  ) {
    Store.app.busy = true;

    /// 六秒收不到超声机的信息就结束loading状态
    Future.delayed(Duration(milliseconds: 3000), () {
      Store.app.busy = false;
    });

    return rpc.liveConsultation.controlParameterAsync(
      ControlDeviceParameterInConsultationRequest(
        token: Store.user.token,
        controlType: controlType,
        isNeedSyn: true,
        consultationCode: consultationCode,
        parameters: parameters,
      ),
    );
  }

//完善会诊信息
  @override
  Future<bool> improveConsultationInfo({
    String? consultationCode,
    String? patientCode,
    List<String>? appointmentScanningPosition,
    String? appointmentDiseaseName,
    String? preliminaryDiagnosis,
    PatientInfo? patientInfo,
  }) async {
    try {
      return await rpc.liveConsultation
          .improveConsultationInfoAsync(ImproveConsultationInfoRequest(
        consultationCode: consultationCode,
        patientCode: patientCode,
        scanPositions: appointmentScanningPosition,
        diseases: appointmentDiseaseName,
        primaryDiagnosis: preliminaryDiagnosis,
        patientDatas: convertPatientInfoToPatientDatas(patientInfo),
        token: token,
      ));
    } catch (e) {
      logger.e(
          'AppointmentConsultationController improveConsultationInfo ex:', e);
    }
    return false;
  }

  List<DataItemDTO>? convertPatientInfoToPatientDatas(
      PatientInfo? patientInfo) {
    if (patientInfo == null) {
      return [];
    }
    return [
      DataItemDTO(
        key: 'Phone',
        value: FEncryptHelper.encodeBase64(
          patientInfo.phone ?? '',
        ),
      ),
      DataItemDTO(
        key: 'AgeUnits',
        value: patientInfo.ageUnits ?? 'Year',
      ),
      DataItemDTO(
        key: 'AgeMonth',
        value: patientInfo.ageMonth,
      ),
      DataItemDTO(
        key: 'AgeWeek',
        value: patientInfo.ageWeek,
      ),
      DataItemDTO(
        key: 'AgeDay',
        value: patientInfo.ageDay,
      ),
      DataItemDTO(
        key: 'Sex',
        value: patientInfo.sex,
      ),
      DataItemDTO(
        key: 'Anamnesis',
        value: patientInfo.anamnesis,
      ),
      DataItemDTO(
        key: 'AgeYear',
        value: patientInfo.ageYear,
      ),
    ];
  }

  @override
  Future<GetEmergencySettingResult> getEmergencySettingAsync() async {
    return await rpc.liveConsultation.getEmergencySettingAsync(
      GetEmergencySettingRequest(token: token),
    );
  }

//--------------------------------------------------------------

  void _onSendInteractiveBoardDataHandler(
      SendInteractiveBoardDataNotification message) {
    message.boardData;
    if (message.boardData != null) {
      if (message.isClear) {
        this.onWhiteboardDataReceive.emit(
            this, jsonEncode({'isClear': 'true', 'u_Id': message.userCode}));
      } else {
        this.onWhiteboardDataReceive.emit(this, message.boardData!);
      }
    }
  }

  void _onleaveConsultationHandler(LeaveLiveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    var leaverInfo = message.leaverInfo;
    if (leaverInfo != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          id: leaverInfo.id,
          name: leaverInfo.name,
          headImageToken: leaverInfo.headImageUrl,
        )
      ];
    }
    this.onLeaveConsultation.emit(
          this,
          consulation,
        );
  }

  void _onInviteLiveConsultHandler(InviteLiveConsultationNotification message) {
    var liveConsultation = LiveConsultation(
      consultationCode: message.consultationCode,
      roomNo: message.roomNo,
    );
    var initiator = message.initiator;
    if (initiator != null) {
      liveConsultation.memberLiveDatas = [
        ConsultationMember.fromDto(initiator)
            .fixMergedVideoOutputSize()
            .fixOnlyCamera()
      ];
    }
    this.onInviteLiveConsultation.emit(this, liveConsultation);
  }

  void _onCloseLiveConsultHandler(CloseLiveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
      initiatorCode: message.initiatorCode,
    );
    this.onCloseConsultation.emit(
          this,
          consulation,
        );
  }

  void _onJoinLiveConsultHandler(JoinLiveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    var joiner = message.joiner;
    if (joiner != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          id: joiner.id,
          name: joiner.name,
          isOnline: joiner.isOnline,
          mute: joiner.mute,
          isInitiator: joiner.id == Store.user.code,
          liveData: joiner.liveData,
          headImageToken: joiner.headImageUrl,
          index: joiner.sortNumber,
        )
      ];
    }
    this.onJoinConsultation.emit(
          this,
          consulation,
        );
  }

  void _onJoinInLiveConsultationHandler(
      JoinInLiveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    var joiner = message.joiner;
    if (joiner != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          id: joiner.id,
          name: joiner.name,
          isOnline: joiner.isOnline,
          mute: joiner.mute,
          isInitiator: joiner.isInitiator,
          liveData: joiner.liveData,
          headImageToken: joiner.headImageUrl,
          sortLevel: joiner.sortLevel,
        )
      ];
      Get.find<IRtmpMockRtcManager>().handleRemoteJoinIn(joiner);
    }
    this.onJoinInConsultation.emit(
          this,
          consulation,
        );
  }

  void _onNetworkErrConsultationHandler(
      NetworkErrConsultationNotification message) {
    var networkErrMemberInfo = message.networkErrMemberInfo;
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    if (networkErrMemberInfo != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          id: networkErrMemberInfo.id,
          name: networkErrMemberInfo.name,
          headImageToken: networkErrMemberInfo.headImageUrl,
        )
      ];
    }
    this.onNetworkErrConsultation.emit(
          this,
          consulation,
        );
  }

  void _onDeviceParametersNotificationHandler(
      DeviceParametersNotification message) {
    var deviceParametersInfo = message;
    this.onDeviceParametersNotification.emit(
          this,
          deviceParametersInfo,
        );
    cacheDeviceParametersNotification = deviceParametersInfo;
  }

  void _onCancelInvitingInLiveCourseNotificationHandler(
      CancelInvitingInLiveCourseNotification message) {
    var notification = message;
    this.onCancelInvitingInLiveCourseNotification.emit(
          this,
          notification,
        );
  }

  void _onCancelInvitingHandler(
      CancelInvitingInLiveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
      userCode: message.userCodes!.first,
    );
    this.onCancelInvitingConsultation.emit(
          this,
          consulation,
        );
  }

  void _onInviteInLiveHandler(InviteInLiveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
      roomNo: message.roomNo,
      operator: message.operator,
    );
    consulation.consultationMemberConvert(message.memberLiveDatas ?? []);
    this.onInviteeInLiveConsultation.emit(
          this,
          consulation,
        );
  }

  void _onAcceptLiveConsultationHandler(
      AcceptLiveConsultationNotification message) {
    var accepter = message.accepter;
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    if (accepter != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          isOnline: accepter.isOnline,
          mute: accepter.mute,
          liveData: accepter.liveData,
          id: accepter.id,
          name: accepter.name,
          headImageToken: accepter.headImageUrl,
        )
      ];
      Get.find<IRtmpMockRtcManager>().handleRemoteAccept(accepter);
    }
    this.onAcceptConsultation.emit(
          this,
          consulation,
        );
  }

  void _onRejectLiveConsultationHandler(
      RejectLiveConsultationNotification message) {
    var accepter = message.rejecter;
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    if (accepter != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          id: accepter.id,
          name: accepter.name,
          headImageToken: accepter.headImageUrl,
        )
      ];
    }
    this.onRejectConsultation.emit(
          this,
          consulation,
        );
  }

  void _onCancelLiveConsulation(CancelLiveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
      initiatorCode: message.initiatorCode,
    );
    this.onCancelConsultation.emit(
          this,
          consulation,
        );
  }

  void _onMuteLiveConsultationHandler(
      MuteLiveConsultationNotification message) {
    var member = message.muterInfo;
    var memberId = '';
    if (member != null) {
      memberId = member.id ?? '';
    }
    Get.find<IRtmpMockRtcManager>().handleRemoteMuteAudio(
      memberId,
      message.mute,
    );
    this.onMemberMute.emit(
          this,
          ConsultationMember(mute: message.mute, id: memberId),
        );
  }

  //成员启用或关闭摄像头通知
  void _onSwitchVideoPlayConsultationHandler(
      SwitchLiveConsultationVideoNotification message) {
    var member = message.switcherInfo;
    var memberId = '';
    if (member != null) {
      memberId = member.id ?? '';
    }
    Get.find<IRtmpMockRtcManager>().handleRemoteMuteVideo(
      memberId,
      !message.opened,
    );
    this.onSwitchVideoPlay.emit(
          this,
          ConsultationMember(videoOpend: message.opened, id: memberId),
        );
  }

  //会诊成员心跳断开离开
  void _onHeartRateLeaveConsultationHandler(
      HeartRateLeaveConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    var leaverInfo = message.leaverInfo;
    if (leaverInfo != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          id: leaverInfo.id,
          name: leaverInfo.name,
          headImageToken: leaverInfo.headImageUrl,
        )
      ];
      Get.find<IRtmpMockRtcManager>().handleRemoteLeave(leaverInfo);
    }
    this.onLeaveConsultation.emit(
          this,
          consulation,
        );
  }

  void _onHeartRateJoinConsultationHandler(
      HeartRateJoinConsultationNotification message) {
    LiveConsultationJoinerInfo? accepter = message.joiner;
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    LiveMemberEnum memberType = LiveMemberEnum.User;

    if (accepter != null) {
      if (accepter.consultationDeviceInfo != null) {
        memberType = LiveMemberEnum.Device;
      }
      consulation.memberLiveDatas = [
        ConsultationMember(
          memberType: memberType,
          isOnline: accepter.isOnline,
          mute: accepter.mute,
          liveData: accepter.liveData,
          id: accepter.id,
          name: accepter.name,
          headImageToken: accepter.headImageUrl,
          mergedChannel:
              accepter.consultationDeviceInfo?.mergedChannel ?? false,
          consultationDeviceInfo: accepter.consultationDeviceInfo,
          videoDeviceInfos:
              accepter.consultationDeviceInfo?.videoDeviceOutputList,
          isOldPlatform: accepter.isOldPlatform,
          supportRtc: accepter.supportRtc,
          mergedVideoOutputWidth:
              accepter.consultationDeviceInfo?.mergedVideoOutputWidth ?? 0,
          mergedVideoOutputHeight:
              accepter.consultationDeviceInfo?.mergedVideoOutputHeight ?? 0,
        ).fixMergedVideoOutputSize().fixOnlyCamera()
      ];
    }
    this.onJoinConsultation.emit(
          this,
          consulation,
        );
  }

  void _onChangeConsultationHandler(ChangeConsultationNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
      roomNo: message.roomNo,
    );
    consulation.consultationMemberConvert(message.memberLiveDatas ?? []);
    this.onChangeConsultation.emit(this, consulation);
  }

  void _onCloseConsultationDueToChangeHandler(
      CloseConsultationDueToChangeNotification message) {
    this.onCloseConsultationDueToChange.emit(
        this, LiveConsultation(consultationCode: message.consultationCode));
  }

  void _onEmergencyCallNotificationHandler(EmergencyCallNotification message) {
    var liveConsultation = LiveConsultation(
      consultationCode: message.consultationCode,
      roomNo: message.roomNo,
    );
    var initiator = message.initiator;
    if (initiator != null) {
      liveConsultation.memberLiveDatas = [
        ConsultationMember.fromDto(initiator)
            .fixMergedVideoOutputSize()
            .fixOnlyCamera()
      ];
    }
    this.onInviteLiveConsultation.emit(this, liveConsultation);
  }

  void _onEmergencyCallFailed(EmergencyCallFailedNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    this.onCancelInvitingConsultation.emit(
          this,
          consulation,
        );
  }

  @override
  Future<void> trtcRetryLoadDevice(String consultationCode) async {
    await rpc.liveConsultation.deviceJoinInLiveConsultationAsync(
      JoinLiveConsultationRequest(
        consultationCode: consultationCode,
        token: token,
      ),
    );
  }

  @override
  Future<void> rtmpRetryLoadDevice(String consultationCode) async {
    final result = await rpc.liveConsultation.deviceJoinInLiveConsultationAsync(
      JoinLiveConsultationRequest(
        token: Store.user.token,
        consultationCode: consultationCode,
        checkOnly: false,
      ),
    );
    Get.find<IRtmpMockRtcManager>().updateDevice(result);
  }

  void _onRejectInviteLiveConsultationHandler(
      RejectInviteLiveConsultationNotification message) {
    var accepter = message.rejecter;
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
    );
    if (accepter != null) {
      consulation.memberLiveDatas = [
        ConsultationMember(
          id: accepter.id,
          name: accepter.name,
          headImageToken: accepter.headImageUrl,
        )
      ];
    }
    this.onRejectConsultation.emit(
          this,
          consulation,
        );
  }

  void _onAnswerTimeoutHandler(ConsultationAnswerTimeoutNotification message) {
    var consulation = LiveConsultation(
      consultationCode: message.consultationCode,
      userCode: message.userCode,
    );
    this.onCancelInvitingConsultation.emit(
          this,
          consulation,
        );
  }

  ///获取输出高度
  double getVideoDeviceInfoHeight(
      {VideoDeviceSourceTypeEnum videoDeviceSourceType =
          VideoDeviceSourceTypeEnum.Desktop,
      required List<VideoDeviceOutputInfo> videoDeviceInfos}) {
    var device = videoDeviceInfos.firstWhere(
        (element) => element.videoDeviceSourceType == videoDeviceSourceType);
    return device.outputHeight.toDouble();
  }

  ///获取输出宽度
  double getVideoDeviceInfoWidth(
      {VideoDeviceSourceTypeEnum videoDeviceSourceType =
          VideoDeviceSourceTypeEnum.Desktop,
      required List<VideoDeviceOutputInfo> videoDeviceInfos}) {
    var device = videoDeviceInfos.firstWhere(
        (element) => element.videoDeviceSourceType == videoDeviceSourceType);
    return device.outputWidth.toDouble();
  }
}
