import 'dart:convert';
import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';

class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
  ///////////////////// Web RTC Video Calling //////////////////////
  // Video Call
  late RTCPeerConnection _peerConnection;
  RTCVideoRenderer _localVideoRenderer = RTCVideoRenderer();
  final RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();

  MediaStream? _localStream;
  MediaStream? _remoteStream;

  void initCallListeners() {
    chatHubConnection.on("OnCallAcceptedAsync", onCallAcceptedAsync);
    chatHubConnection.on("OnIceCandidateAsync", onIceCandidateAsync);
    chatHubConnection.on("OnOfferAsync", onOfferAsync);
    chatHubConnection.on("OnAnswerOffer", onAnswerOffer);
    chatHubConnection.on("OnHangUpAsync", onHangUpAsync);
    chatHubConnection.on("OnCallDeclinedAsync", onCallDeclinedAsync);
  }

  //Video Constraints
  var videoConstraints = {
    "video": {
      "mandatory": {
        "width": {"min": 320},
        "height": {"min": 180}
      },
      "optional": [
        {
          "width": {"max": 1280}
        },
        {"frameRate": 25},
        {"facingMode": "user"}
      ]
    },
    "frameRate": 25,
    "width": 420, //420,//640,//1280,
    "height": 240 //240//480//720
  };

  // Audio Constraints
  var audioConstraints = {
    "sampleRate": 8000,
    "sampleSize": 16,
    "channelCount": 2,
    "echoCancellation": true,
    "audio": true,
  };

  Future<RTCPeerConnection> _createPeerConnection() async {
    //  {"url": "stun:stun.l.google.com:19302"},
    Map<String, dynamic> configuration = {
      "iceServers": [
        {"urls": 'stun:15.185.116.59:3478'},
        {"urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin"}
      ]
    };

    Map<String, dynamic> offerSdpConstraints = {
      "mandatory": {
        "OfferToReceiveAudio": true,
        "OfferToReceiveVideo": true,
      },
      "optional": [],
    };

    RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints);
    // if (pc != null) print(pc);
    //pc.addStream(widget.localStream);

    pc.onIceCandidate = (e) {
      if (e.candidate != null) {
        print(json.encode({
          'candidate': e.candidate.toString(),
          'sdpMid': e.sdpMid.toString(),
          'sdpMlineIndex': e.sdpMLineIndex,
        }));
      }
    };
    pc.onIceConnectionState = (e) {
      print(e);
    };
    pc.onAddStream = (stream) {
      print('addStream: ' + stream.id);
      _remoteRenderer.srcObject = stream;
    };
    return pc;
  }

  void init() {
    initRenderers();
    _createPeerConnection().then((pc) {
      _peerConnection = pc;
      // _setRemoteDescription(widget.info);
    });
  }

  void initRenderers() {
    _localVideoRenderer.initialize();
    _remoteRenderer.initialize();
    initLocalCamera();
  }

  void initLocalCamera() async {
    _localStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
    _localVideoRenderer.srcObject = _localStream;
    // _localVideoRenderer.srcObject = await navigator.mediaDevices
    //     .getUserMedia({'video': true, 'audio': true});
    print('this source Object');
    print('this suarce  ${_localVideoRenderer.srcObject != null}');
    notifyListeners();
  }

  void startCall({required String callType}) {}

  void endCall() {}

  void checkCall(Map<String, dynamic> message) {
    switch (message["callStatus"]) {
      case 'connected':
        {}
        break;
      case 'offer':
        {}
        break;
      case 'accept':
        {}
        break;
      case 'candidate':
        {}
        break;
      case 'bye':
        {}
        break;
      case 'leave':
        {}
        break;
    }
  }

  //// Listeners Methods ////

  void onCallAcceptedAsync(List<Object?>? params) {}

  void onIceCandidateAsync(List<Object?>? params) {}

  void onOfferAsync(List<Object?>? params) {}

  void onAnswerOffer(List<Object?>? params) {}

  void onHangUpAsync(List<Object?>? params) {}

  void onCallDeclinedAsync(List<Object?>? params) {}

  //// Invoke Methods

  Future<void> invoke({required String invokeMethod, required String currentUserID, required String targetUserID, bool isVideoCall = false, var data}) async {
    List<Object> args = [];
    if (invokeMethod == "answerCallAsync") {
      args = [currentUserID, targetUserID];
    } else if (invokeMethod == "CallUserAsync") {
      args = [currentUserID, targetUserID, isVideoCall];
    } else if (invokeMethod == "IceCandidateAsync") {
      args = [targetUserID, data];
    } else if (invokeMethod == "OfferAsync") {
      args = [targetUserID, data];
    } else if (invokeMethod == "AnswerOfferAsync") {
      args = [targetUserID, data];
      //json In Data
    }
    await chatHubConnection.invoke(invokeMethod, args: args);
  }

  void stopListeners() async {
    chatHubConnection.off('OnCallDeclinedAsync');
    chatHubConnection.off('OnCallAcceptedAsync');
    chatHubConnection.off('OnIceCandidateAsync');
    chatHubConnection.off('OnAnswerOffer');
  }
}
