package com.rnenxrtc;

import static androidx.core.content.ContentProviderCompat.requireContext;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Base64;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.Toast;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.MediaStream;
import org.webrtc.VideoTrack;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Nonnull;

import enx_rtc_android.Controller.EnxActiveTalkerListObserver;
import enx_rtc_android.Controller.EnxAdvancedOptionsObserver;
import enx_rtc_android.Controller.EnxAnnotationObserver;
import enx_rtc_android.Controller.EnxBandwidthObserver;
import enx_rtc_android.Controller.EnxBreakoutRoomObserver;
import enx_rtc_android.Controller.EnxCanvasObserver;
import enx_rtc_android.Controller.EnxChairControlObserver;
import enx_rtc_android.Controller.EnxCustomDataStorageObserver;
import enx_rtc_android.Controller.EnxFileShareObserver;
import enx_rtc_android.Controller.EnxForegroundService;
import enx_rtc_android.Controller.EnxHlsStreamObserver;
import enx_rtc_android.Controller.EnxLiveRecordingObserver;
import enx_rtc_android.Controller.EnxLiveStreamingObserver;
import enx_rtc_android.Controller.EnxLockRoomManagementObserver;
import enx_rtc_android.Controller.EnxLogsObserver;
import enx_rtc_android.Controller.EnxMuteAudioStreamObserver;
import enx_rtc_android.Controller.EnxMuteRoomObserver;
import enx_rtc_android.Controller.EnxMuteVideoStreamObserver;
import enx_rtc_android.Controller.EnxNetworkObserever;
import enx_rtc_android.Controller.EnxOutBoundCallObserver;
import enx_rtc_android.Controller.EnxPermissionObserver;
import enx_rtc_android.Controller.EnxPlayerStatsObserver;
import enx_rtc_android.Controller.EnxPlayerView;
import enx_rtc_android.Controller.EnxReconnectObserver;
import enx_rtc_android.Controller.EnxRecordingObserver;
import enx_rtc_android.Controller.EnxRemoteStreamMediaObserver;
import enx_rtc_android.Controller.EnxRoom;
import enx_rtc_android.Controller.EnxRoomMuteUserObserver;
import enx_rtc_android.Controller.EnxRoomObserver;
import enx_rtc_android.Controller.EnxRtc;
import enx_rtc_android.Controller.EnxScreenShareObserver;
import enx_rtc_android.Controller.EnxScreenShotObserver;
import enx_rtc_android.Controller.EnxStatsObserver;
import enx_rtc_android.Controller.EnxStream;
import enx_rtc_android.Controller.EnxStreamObserver;
import enx_rtc_android.Controller.EnxSwitchRoomObserver;
import enx_rtc_android.Controller.EnxTalkerNotificationObserver;
import enx_rtc_android.Controller.EnxTalkerObserver;
import enx_rtc_android.Controller.EnxTroubleShooterObserver;
import enx_rtc_android.Controller.EnxUtilityManager;
import enx_rtc_android.Controller.EnxTranscriptionObserver;

public class EnxRoomManager extends ReactContextBaseJavaModule implements EnxRoomObserver, EnxStreamObserver, EnxRecordingObserver, EnxScreenShareObserver, EnxTalkerObserver, EnxLogsObserver, EnxChairControlObserver, EnxMuteRoomObserver, EnxMuteAudioStreamObserver, EnxMuteVideoStreamObserver, EnxStatsObserver, EnxPlayerStatsObserver, EnxBandwidthObserver, EnxNetworkObserever, EnxReconnectObserver, EnxScreenShotObserver, EnxAdvancedOptionsObserver, EnxCanvasObserver, EnxFileShareObserver, EnxLockRoomManagementObserver, EnxOutBoundCallObserver, EnxAnnotationObserver, EnxActiveTalkerListObserver, EnxTalkerNotificationObserver, EnxBreakoutRoomObserver, EnxTroubleShooterObserver, EnxSwitchRoomObserver, EnxLiveRecordingObserver, EnxRemoteStreamMediaObserver, EnxRoomMuteUserObserver, EnxTranscriptionObserver, EnxPermissionObserver, EnxHlsStreamObserver, EnxLiveStreamingObserver, EnxCustomDataStorageObserver {

    private ReactApplicationContext mReactContext = null;
    private ArrayList<String> jsEvents = new ArrayList<String>();
    private ArrayList<String> componentEvents = new ArrayList<String>();
    private final String roomPreface = "room:";
    private final String streamPreface = "stream:";
    private EnxRtc enxRtc;
    private EnxStream localStream;
    private EnxRoom mEnxRoom;
    EnxRN sharedState;
    private String localStreamId;
    private boolean selectedCamera;
    private List<EnxStream> tempAtList = new ArrayList<EnxStream>();
    private Boolean cameraPosition = true;

    public EnxRoomManager(ReactApplicationContext reactContext) {
        super(reactContext);
        sharedState = EnxRN.getSharedState();
        mReactContext = reactContext;
        mReactContext.addActivityEventListener(activityEventListener);
    }
    // Define the ActivityEventListener to listen for the activity result
    private final ActivityEventListener activityEventListener = new ActivityEventListener() {
        @Override
        public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
            if (requestCode == REQUEST_CODE) {
                if (resultCode == Activity.RESULT_OK && data != null) {
                    // User granted permission for screen capture
                    handleScreenCaptureResult(data);
                } else {
                    // Handle permission denial
                    Toast.makeText(getReactApplicationContext(), "Screen share permission denied", Toast.LENGTH_SHORT).show();

                }
            }
        }

        @Override
        public void onNewIntent(Intent intent) {

        }


    };

    @ReactMethod
    public void setNativeEvents(ReadableArray events) {
        try {
            for (int i = 0; i < events.size(); i++) {
                jsEvents.add(events.getString(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void initRoom() {
        try {
            cameraPosition=true;
            enxRtc = new EnxRtc(mReactContext.getCurrentActivity(), this, this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void removeNativeEvents(ReadableArray events) {
        try {
            for (int i = 0; i < events.size(); i++) {
                jsEvents.remove(events.getString(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void setJSComponentEvents(ReadableArray events) {
        try {
            for (int i = 0; i < events.size(); i++) {
                componentEvents.add(events.getString(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void removeJSComponentEvents(ReadableArray events) {
        try {
            for (int i = 0; i < events.size(); i++) {
                componentEvents.remove(events.getString(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void joinRoom(String token, ReadableMap localStreamInfo, ReadableMap roomInfo, ReadableArray advanceOptions) {
        if (enxRtc != null) {
            try {
                ConcurrentHashMap<String, EnxStream> mEnxStrm = sharedState.getLocalStream();
                if (localStream != null) {
                    mEnxStrm.remove("abc-123-xyz");
                    localStream = null;
                }
                localStream = enxRtc.joinRoom(token, EnxUtils.convertMapToJson(localStreamInfo), EnxUtils.convertMapToJson(roomInfo), EnxUtils.convertArrayToJson(advanceOptions));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @ReactMethod
    public void muteSelfAudio(String localStreamId, boolean value) {
        try {
            ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
            EnxStream stream = mLocalStream.get(localStreamId);
            if (stream != null) {
                stream.muteSelfAudio(value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void muteSelfVideo(String localStreamId, boolean value) {
        try {
            ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
            EnxStream stream = mLocalStream.get(localStreamId);
            if (stream != null) {
                stream.muteSelfVideo(value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void initStream(String streamId,boolean isFrontCamera) {
        try {
            // cameraPosition = isFrontCamera;
            ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getLocalStream();
            if (streamId.equals("abc-123-xyz")) {
                try {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("audio", true);
                    jsonObject.put("video", true);
                    jsonObject.put("data", true);
                    jsonObject.put("framerate", 30);
                    JSONObject videoSize = new JSONObject();
                    videoSize.put("minWidth", 320);
                    videoSize.put("minHeight", 180);
                    videoSize.put("maxWidth", 1280);
                    videoSize.put("maxHeight", 720);
                    jsonObject.put("videoSize", videoSize);
                    jsonObject.put("audioMuted", false);
                    jsonObject.put("videoMuted", false);
                    EnxRoom room = new EnxRoom(mReactContext.getCurrentActivity());
                     mEnxRoom=room;
                    localStream = room.getPreview(jsonObject);

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                if (localStream != null) {
                    mEnxStream.remove("abc-123-xyz");
                }
            }
            if (localStream != null) {
                mEnxStream.put(streamId, localStream);
                localStreamId = streamId;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @ReactMethod
    public void cleanPreviewResource(){
        if (localStream != null) {
            if (localStream.getMedia() != null) {
                MediaStream mStrea =  localStream.getMedia();
                for (VideoTrack track : mStrea.videoTracks) {
                    track.setEnabled(false);
                    track.dispose(); // Dispose of the track to release resources
                }
            }
            // If you're using a VideoCapturer, stop itq
            if (mEnxRoom.mVideoCapturer != null) {
                try {
                    mEnxRoom.mVideoCapturer.stopCapture();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mEnxRoom.mVideoCapturer.dispose();
                mEnxRoom.mVideoCapturer = null;
            }
        }
        if (mEnxRoom != null){
            mEnxRoom = null;
        }
    }

    @ReactMethod
    public void publish() {
        try {
            if (localStreamId != null) {
                ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getLocalStream();
                EnxStream localStream = mEnxStream.get(localStreamId);
                mEnxRoom.publish(localStream);
                if (localStream != null) {
                    localStream.setMuteAudioStreamObserver(this);
                    localStream.setMuteVideoStreamObserver(this);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void subscribe(String streamId, Callback callback) {
        try {
            ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
            mEnxRoom.subscribe(mSubscriberStreams.get(streamId));
            callback.invoke("Stream subscribed successfully.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void getLocalStreamId(Callback callback) {
        callback.invoke(localStreamId);
    }

     @ReactMethod
    public void switchCamera(String localStreamId) {
        try {
            ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
            EnxStream stream = mLocalStream.get(localStreamId);
            if (stream != null) {
                stream.switchCamera();

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


     @ReactMethod
    public void switchCameraPreview() {
        try {
            ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
            EnxStream stream = mLocalStream.get("abc-123-xyz");
            if (stream != null) {
                stream.switchCameraPreview();

            }
            cameraPosition = !cameraPosition;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void startRecord() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.startRecord();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void stopRecord() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.stopRecord();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static final int REQUEST_CODE = 42;
private void startForegroundServices(boolean isScreenShare,EnxStream enxStream ){
    // Start the foreground service (both for below and above Android 13)
    Intent serviceIntent = new Intent(getReactApplicationContext(), EnxForegroundService.class);
    serviceIntent.setAction("ACTION_START");

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // For Android Oreo (API 26) and above, use startForegroundService()
        getReactApplicationContext().startForegroundService(serviceIntent);
    } else {
        // For devices below Oreo, use startService()
        getReactApplicationContext().startService(serviceIntent);
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        // Handle Android 13 and above
        if (MediaProjectionIntentHolder.intent != null) {
            // Use the stored intent for screen capture (no need to request permission again)
            if (mEnxRoom != null) {
                if(isScreenShare){
                    mEnxRoom.startScreenShare();
                }else{
                    mEnxRoom.startAnnotation(enxStream);
                }

            }

        } else {
            // Request permission if no intent is available
            if (getReactApplicationContext().getCurrentActivity() != null) {
                // initializeActivityResultLauncher(getReactApplicationContext().getCurrentActivity());

                MediaProjectionManager projectionManager =
                        (MediaProjectionManager) getReactApplicationContext().getCurrentActivity().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
                Intent captureIntent = projectionManager.createScreenCaptureIntent();

                boolean screenRecordingSupported = getReactApplicationContext().getPackageManager()
                        .queryIntentActivities(captureIntent, 0)
                        .size() > 0;

                if (screenRecordingSupported) {

                    getCurrentActivity().startActivityForResult(captureIntent, REQUEST_CODE);

                } else {
                    Toast.makeText(mReactContext,"Screen share is not supported on this device",Toast.LENGTH_SHORT).show();

                }
            }
        }
    } else{
        if (mEnxRoom != null) {
            if(isScreenShare){
                mEnxRoom.startScreenShare();
            }else{
                mEnxRoom.startAnnotation(enxStream);
            }
        }
    }

}
boolean isShareRequest=false;
    @ReactMethod
    public void startScreenShare() {
        try {
            isShareRequest=true;
            startForegroundServices(true,null);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    // Handle the result of screen capture permission request
    private void handleScreenCaptureResult(Intent data) {
        // Store the intent for future use
        MediaProjectionIntentHolder.intent = data;
        // You can start screen recording or initiate a recording service
          if (mEnxRoom != null) {
              if(isShareRequest){
                  mEnxRoom.startScreenShare();
              }else{
                  mEnxRoom.startAnnotation(mEnxAnnotationStream);
              }

        }
    }
 private void stopForegroundService(){
     getReactApplicationContext().removeActivityEventListener(activityEventListener);
     Intent serviceIntent = new Intent(getReactApplicationContext(), EnxForegroundService.class);
     serviceIntent.setAction("ACTION_STOP");
     getReactApplicationContext().stopService(serviceIntent);
 }

    @ReactMethod
    public void stopScreenShare() {
        try {
            isShareRequest=false;
            stopForegroundService();
            if (mEnxRoom != null) {
                mEnxRoom.stopScreenShare();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void getDevices(Callback callback) {
        int maxRetries = 3;
        int attempts = 0;
        boolean success = false;
        while (attempts < maxRetries && !success) {
            try {
                if (mEnxRoom != null) {
                    // Get the list of devices from mEnxRoom
                    ArrayList<String> deviceList = (ArrayList<String>) mEnxRoom.getDevices();
                    WritableArray array = Arguments.createArray();
                    // Iterate through the device list
                    for (String device : deviceList) {
                        if (device != null) {
                            array.pushString(device.trim());
                        } else {
                            array.pushNull();
                        }
                    }

                    // Invoke the callback with the array
                    callback.invoke(array);

                    // Mark the operation as successful
                    success = true;
                }
            } catch (ClassCastException e) {
                // Handle specific exception if the type casting fails
                e.printStackTrace();
                // Log the error or handle it as needed
            } catch (Exception e) {
                // Handle any other exceptions
                e.printStackTrace();
                // Log the error or handle it as needed
            } finally {
                attempts++;
                if (!success && attempts < maxRetries) {
                    // Optionally, add a delay before retrying
                    try {
                        Thread.sleep(1000); // Sleep for 1 second before retrying
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }

        if (!success) {
            // Handle the case where all retries failed
            System.err.println("Failed to get device list after " + maxRetries + " attempts.");
            // Optionally, invoke the callback with an error or handle it accordingly
            callback.invoke("Error: Failed to get device list after multiple attempts.");
        }


    }

    @ReactMethod
    public void getSelectedDevice(Callback callback) {
        try {
            if (mEnxRoom != null) {
                callback.invoke(mEnxRoom.getSelectedDevice());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void getMaxTalkers() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.getMaxTalkers();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void getTalkerCount() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.getTalkerCount();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void setTalkerCount(int number) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.setTalkerCount(number);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void hardMute() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.hardMute();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void hardUnmute() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.hardUnMute();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void enableLogs(boolean status) {
        EnxUtilityManager enxLogsUtil = EnxUtilityManager.getInstance();
        enxLogsUtil.enableLogs(status);
    }

    @ReactMethod
    public void switchMediaDevice(String audioDevice) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.switchMediaDevice(audioDevice);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void requestFloor() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.requestFloor();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void grantFloor(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.grantFloor(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void denyFloor(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.denyFloor(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void releaseFloor(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.releaseFloor(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void cancelFloor() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.cancelFloor();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void finishFloor() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.finishFloor();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void inviteToFloor(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.inviteToFloor(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void cancelFloorInvite(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.cancelFloorInvite(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void rejectInviteFloor(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.rejectInviteFloor(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void acceptInviteFloorRequest(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.acceptInviteFloorRequest(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @ReactMethod
    public void postClientLogs() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.postClientLogs();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void changeToAudioOnly(boolean value) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.setAudioOnlyMode(value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void hardMuteAudio(String streamId, String clientId) {
        try {
            ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getLocalStream();
            EnxStream localStream = mEnxStream.get(streamId);
            if (localStream != null) {
                localStream.hardMuteAudio(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void hardUnmuteAudio(String streamId, String clientId) {
        try {
            ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getLocalStream();
            EnxStream localStream = mEnxStream.get(streamId);
            if (localStream != null) {
                localStream.hardUnMuteAudio(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void hardMuteVideo(String streamId, String clientId) {
        try {
            ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getLocalStream();
            EnxStream localStream = mEnxStream.get(streamId);
            if (localStream != null) {
                localStream.hardMuteVideo(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void hardUnmuteVideo(String streamId, String clientId) {
        try {
            ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getLocalStream();
            EnxStream localStream = mEnxStream.get(streamId);
            if (localStream != null) {
                localStream.hardUnMuteVideo(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void stopVideoTracksOnApplicationBackground(boolean videoMuteRemoteStream, boolean videoMuteLocalStream) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.stopVideoTracksOnApplicationBackground(videoMuteRemoteStream, videoMuteLocalStream);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void startVideoTracksOnApplicationForeground(boolean restoreVideoRemoteStream, boolean restoreVideoLocalStream) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.startVideoTracksOnApplicationForeground(restoreVideoRemoteStream, restoreVideoLocalStream);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void changePlayerScaleType(final int mode, final String streamId) {
        try {
            if (mReactContext.getCurrentActivity() == null) {
                return;
            }
            mReactContext.getCurrentActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ConcurrentHashMap<String, EnxPlayerView> mPlayers = sharedState.getPlayerView();
                    if (mPlayers.containsKey(streamId)) {
                        if (mode == 1) {
                            mPlayers.get(streamId).setScalingType(EnxPlayerView.ScalingType.SCALE_ASPECT_FILL);
                        } else {
                            mPlayers.get(streamId).setScalingType(EnxPlayerView.ScalingType.SCALE_ASPECT_FIT);
                        }
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void setZOrderMediaOverlay(final boolean isOverlay, final String streamId) {
        try {
            if (mReactContext.getCurrentActivity() == null) {
                return;
            }
            mReactContext.getCurrentActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ConcurrentHashMap<String, EnxPlayerView> mPlayers = sharedState.getPlayerView();
                    if (mPlayers.containsKey(streamId)) {
                        mPlayers.get(streamId).setZOrderMediaOverlay(isOverlay);
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void setConfigureOption(final ReadableMap dataObject, final String streamId) {
        Log.e("setConfigureOption", dataObject.toString());
    }

    @ReactMethod
    public void enableStats(boolean isEnabled) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.enableStats(true, this);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void enablePlayerStats(boolean isEnabled, String streamId) {
        try {
            ConcurrentHashMap<String, EnxPlayerView> playerView = sharedState.getPlayerView();
            if (playerView.get(streamId) != null) {
                playerView.get(streamId).enablePlayerStats(isEnabled, this);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @ReactMethod
    public void sendData(String streamId, ReadableMap dataObject) {
        try {
            ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getLocalStream();
            EnxStream localStream = mEnxStream.get(streamId);
            JSONObject jsonObject = new JSONObject();
            try {
                jsonObject.put("message", dataObject.getString("message"));
                jsonObject.put("from", dataObject.getString("from"));
                //            jsonObject.put("timestamp", dataObject.getDynamic("timestamp"));
                if (localStream != null) {
                    localStream.sendData(jsonObject);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void sendMessage(String message, boolean broadcast, ReadableArray clientList) {
        try {
            if (mEnxRoom != null) {
                List<String> deconstructedList = new ArrayList<>();
                for (int i = 0; i < clientList.size(); i++) {
                    deconstructedList.add(i, clientList.getString(i));
                }
                mEnxRoom.sendMessage(message, broadcast, deconstructedList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void sendUserData(ReadableMap message, boolean broadcast, ReadableArray clientList) throws JSONException {
        try {
            if (mEnxRoom != null) {
                List<String> deconstructedList = new ArrayList<>();
                for (int i = 0; i < clientList.size(); i++) {
                    deconstructedList.add(i, clientList.getString(i));
                }
                mEnxRoom.sendUserData(EnxUtils.convertMapToJson(message), broadcast, deconstructedList);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @ReactMethod
    public void sendFiles(final boolean broadcast, final ReadableArray clientList) {
        try {
            mReactContext.getCurrentActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (mEnxRoom != null) {
                            mEnxRoom.sendFiles(broadcast, Arguments.toList(clientList), getCurrentActivity());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void downloadFile(ReadableMap data, boolean isAutoSave) throws JSONException {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.downloadFile(EnxUtils.convertMapToJson(data), isAutoSave);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void getAvailableFiles() throws JSONException {
        try {
            if (mEnxRoom != null) {
                JSONObject object = mEnxRoom.getAvailableFiles();
                if (object.optJSONArray("files").length() == 0) {
                    sendEventWithString(this.getReactApplicationContext(), roomPreface + "getAvailableFiles", "No files Available");
                } else {
                    try {
                        sendEventMap(this.getReactApplicationContext(), roomPreface + "getAvailableFiles", EnxUtils.jsonToReact(mEnxRoom.getAvailableFiles()));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void setAdvancedOptions(ReadableArray array) {
        try {
            if (mEnxRoom != null) {
                try {
                    mEnxRoom.setAdvancedOptions(EnxUtils.convertArrayToJson(array), EnxRoomManager.this);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void getAdvancedOptions() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.getAdvancedOptions();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void captureScreenShot(final String streamId) {
        try {
            System.out.println("ENX captureScreenShot ID = " + streamId);
            if (mReactContext.getCurrentActivity() == null) {
                return;
            }
            mReactContext.getCurrentActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ConcurrentHashMap<String, EnxStream> mPlayers = sharedState.getRemoteStream();
                    if (mPlayers.containsKey(streamId)) {
                        System.out.println("ENX containsKey ID = " + streamId);
                        mPlayers.get(streamId).mEnxPlayerView.captureScreenShot(EnxRoomManager.this);
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @ReactMethod
    public void switchUserRole(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.switchUserRole(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void cancelUpload(String upJobId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.cancelUpload(Integer.parseInt(upJobId));
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void cancelDownload(String jobId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.cancelDownload(Integer.parseInt(jobId));
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void cancelAllUploads() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.cancelAllUploads();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void cancelAllDownloads() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.cancelAllDownloads();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void lockRoom() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.lockRoom();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void unLockRoom() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.unLockRoom();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void makeOutboundCall(String number, String callerId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.makeOutboundCall(number, callerId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void sendDTMF(String number, String digits) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.sendDTMF(number, digits);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void extendConferenceDuration() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.extendConferenceDuration();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void destroy() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.destroy();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void dropUser(ReadableArray clientList) {
        try {
            if (mEnxRoom != null) {
                List<String> deconstructedList = new ArrayList<>();
                for (int i = 0; i < clientList.size(); i++) {
                    deconstructedList.add(i, clientList.getString(i));
                }
                mEnxRoom.dropUser(deconstructedList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public WritableMap getRoomMetadata() {
        if (mEnxRoom != null) {
            try {
                return EnxUtils.jsonToReact(mEnxRoom.getRoomMetadata());
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @ReactMethod
    public WritableMap whoAmI() {
        if (mEnxRoom != null) {
            try {
                return EnxUtils.jsonToReact(mEnxRoom.whoAmI());
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @ReactMethod
    public boolean isPublishing() {
        try {
            if (mEnxRoom != null) {
                return mEnxRoom.isPublishing();
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public boolean isRoomActiveTalker() {
        try {
            if (mEnxRoom != null) {
                return mEnxRoom.isRoomActiveTalker();
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public void setAudioOnlyMode(boolean status) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.setAudioOnlyMode(status);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void enableProximitySensor(boolean status) {
        if (mEnxRoom != null) {
            // mEnxRoom.enableProximitySensor(status);
        }
    }

    @ReactMethod
    public void pinUsers(ReadableArray clientIds) {
        try {
            if (mEnxRoom != null) {
                List<String> deconstructedList = new ArrayList<>();
                for (int i = 0; i < clientIds.size(); i++) {
                    deconstructedList.add(i, clientIds.getString(i));
                }
                mEnxRoom.pinUsers(deconstructedList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void unpinUsers(ReadableArray clientIds) {
        try {
            if (mEnxRoom != null) {
                List<String> deconstructedList = new ArrayList<>();
                for (int i = 0; i < clientIds.size(); i++) {
                    deconstructedList.add(i, clientIds.getString(i));
                }
                mEnxRoom.unpinUsers(deconstructedList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void getClientId(Callback callback) {
        try {
            if (mEnxRoom != null) {
                callback.invoke(mEnxRoom.getClientId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public String getRoomId() {
        try {
            if (mEnxRoom != null) {
                return mEnxRoom.getRoomId();
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @ReactMethod
    public String getMode() {
        try {
            if (mEnxRoom != null) {
                return mEnxRoom.getMode();
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @ReactMethod
    public void muteSubscribeStreamsAudio(boolean status) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.muteSubscribeStreamsAudio(status);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public String getRole() {
        try {
            if (mEnxRoom != null) {
                return mEnxRoom.getRole();
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @ReactMethod
    public String getClientName() {
        try {
            if (mEnxRoom != null) {
                return mEnxRoom.getClientName();
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @ReactMethod
    public void setReceiveVideoQuality(ReadableMap map) {
        if (mEnxRoom != null) {
            try {
                mEnxRoom.setReceiveVideoQuality(EnxUtils.convertMapToJson(map));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @ReactMethod
    public String getReceiveVideoQuality(String streamType) {
        try {
            if (mEnxRoom != null) {
                return mEnxRoom.getReceiveVideoQuality(streamType);
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return streamType;
    }

    @ReactMethod
    public void getUserList(Callback callback) {
        try {
            if (mEnxRoom != null) {
                try {
                 callback.invoke(EnxUtils.convertJsonToArray(mEnxRoom.getUserList()));
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
      
    }


    @ReactMethod
    public boolean isLocal(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                return true;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public boolean hasData(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (stream != null) {
                    return stream.hasData();
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (stream != null) {
                    return stream.hasData();
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public boolean hasScreen(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (stream != null) {
                    return stream.hasScreen();
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (stream != null) {
                    return stream.hasScreen();
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public boolean hasAudio(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (stream != null) {
                    return stream.hasAudio();
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (stream != null) {
                    return stream.hasAudio();
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public boolean hasVideo(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (stream != null) {
                    return stream.hasVideo();
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (stream != null) {
                    return stream.hasVideo();
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public boolean isAudioOnlyStream(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (stream != null) {
                    return stream.isAudioOnlyStream();
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (stream != null) {
                    return stream.isAudioOnlyStream();
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @ReactMethod
    public String getReasonForMuteVideo(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (stream != null) {
                    return stream.getReasonForMuteVideo();
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (stream != null) {
                    return stream.getReasonForMuteVideo();
                }
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return streamId;
    }

    @ReactMethod
    public String getMediaType(String streamId) {
        try {
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (stream != null) {
                    return stream.getMediaType();
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (stream != null) {
                    return stream.getMediaType();
                }
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return streamId;
    }
   private EnxStream mEnxAnnotationStream;
    @ReactMethod
    public void startAnnotation(String streamId) {
        try {
            isShareRequest=false;
            if (streamId.equalsIgnoreCase(localStreamId)) {
                ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
                EnxStream stream = mLocalStream.get(localStreamId);
                if (mEnxRoom != null && stream != null) {
                    mEnxAnnotationStream=stream;
                    startForegroundServices(false,stream);
                  //  mEnxRoom.startAnnotation(stream);
                }
            } else {
                ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
                EnxStream stream = mSubscriberStreams.get(streamId);
                if (mEnxRoom != null && stream != null) {
                    startForegroundServices(false,stream);
                    //mEnxRoom.startAnnotation(stream);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void stopAnnotation() {
        try {
            mEnxAnnotationStream=null;
            isShareRequest=false;
            stopForegroundService();
            if (mEnxRoom != null) {
                mEnxRoom.stopAnnotations();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @ReactMethod
    public void disconnect() {
        try {
            if (mEnxRoom != null) {
                ConcurrentHashMap<String, EnxPlayerView> playerView = sharedState.getPlayerView();
                for (String key : playerView.keySet()) {
                    if (key.length() > 1) {
                        EnxPlayerView playerView1 = playerView.get(key);
                        if (playerView1 != null) {
                            playerView1.release();
                            playerView1 = null;
                        }
                    }
                }
                mEnxRoom.disconnect();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Audio Energy
    @ReactMethod
    public void subscribeForTalkerNotification(boolean flag) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.subscribeForTalkerNotification(flag, this);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // Breakout Room
    @ReactMethod
    public void createBreakOutRoom(ReadableMap readableMap) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.createBreakOutRoom(EnxUtils.convertMapToJson(readableMap));
            }
        } catch (Exception exception) {

        }
    }

    @ReactMethod
    public void createAndInviteBreakoutRoom(ReadableMap readableMap) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.createBreakOutRoom(EnxUtils.convertMapToJson(readableMap));
            }
        } catch (Exception exception) {

        }
    }

    @ReactMethod
    public void joinBreakoutRoom(ReadableMap readableMap, ReadableMap streamInfo) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.joinBreakOutRoom(EnxUtils.convertMapToJson(readableMap), EnxUtils.convertMapToJson(streamInfo));
            }
        } catch (Exception exception) {

        }
    }

    @ReactMethod
    public void inviteToBreakOutRoom(ReadableMap readableMap) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.inviteToBreakOutRoom(EnxUtils.convertMapToJson(readableMap));
            }
        } catch (Exception exception) {

        }
    }

    @ReactMethod
    public void pause() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.pause();
            }
        } catch (Exception exception) {

        }
    }

    @ReactMethod
    public void resume() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.resume();
            }
        } catch (Exception exception) {

        }
    }


    @ReactMethod
    public void rejectBreakOutRoom(String roomId) {

        try {
            if (mEnxRoom != null) {
                mEnxRoom.rejectBreakOutRoom(roomId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @ReactMethod
    public void muteRoom(ReadableMap readableMap) {

        if (mEnxRoom != null) {
            try {
                mEnxRoom.muteRoom(EnxUtils.convertMapToJson(readableMap));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

    }

    @ReactMethod
    public void unmuteRoom(ReadableMap readableMap) {

        if (mEnxRoom != null) {
            try {
                mEnxRoom.unmuteRoom(EnxUtils.convertMapToJson(readableMap));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

    }

    // Precall test
    @ReactMethod
    public void clientDiagnostics(ReadableMap readableMap) {
        try {
            if (enxRtc != null) {
                enxRtc.clientDiagnostics(EnxUtils.convertMapToJson(readableMap));
            }
        } catch (Exception exception) {

        }

    }

    //knock -knock
    @ReactMethod
    public void approveAwaitedUser(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.approveAwaitedUser(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void denyAwaitedUser(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.denyAwaitedUser(clientId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //SpotLight
    @ReactMethod
    public void addSpotlightUsers(ReadableArray clientIds) {
        try {
            if (mEnxRoom != null) {
                List<String> deconstructedList = new ArrayList<>();
                for (int i = 0; i < clientIds.size(); i++) {
                    deconstructedList.add(i, clientIds.getString(i));
                }
                mEnxRoom.addSpotlightUsers(deconstructedList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void removeSpotlightUsers(ReadableArray clientIds) {
        try {
            if (mEnxRoom != null) {
                List<String> deconstructedList = new ArrayList<>();
                for (int i = 0; i < clientIds.size(); i++) {
                    deconstructedList.add(i, clientIds.getString(i));
                }
                mEnxRoom.removeSpotlightUsers(deconstructedList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //Switch Room
    @ReactMethod
    public void switchRoomMode(String mode) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.switchRoomMode(mode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Live Recording
    @ReactMethod
    public void startLiveRecording(ReadableMap readableMap) {
        if (mEnxRoom != null) {
            try {
                mEnxRoom.startLiveRecording(EnxUtils.convertMapToJson(readableMap));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @ReactMethod
    public void stopLiveRecording() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.stopLiveRecording();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //Streaming
    @ReactMethod
   public void startStreaming(ReadableMap streamingDetails){
        if (mEnxRoom != null) {
            try {
                mEnxRoom.startStreaming(EnxUtils.convertMapToJson(streamingDetails));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
    @ReactMethod
    public void stopStreaming(ReadableMap streamingDetails){
        if (mEnxRoom != null) {
            try {
                mEnxRoom.stopStreaming(EnxUtils.convertMapToJson(streamingDetails));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
    // Hard Mute-Unmute user Audio
    @ReactMethod
    public void hardMuteUserAudio(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.hardMuteUserAudio(clientId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void hardUnmuteUserAudio(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.hardUnmuteUserAudio(clientId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    // Hard Mute-Unmute user Video
    @ReactMethod
    public void hardMuteUserVideo(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.hardMuteUserVideo(clientId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void hardUnmuteUserVideo(String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.hardUnmuteUserVideo(clientId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void makeOutboundCallwithJoinOption(String number, String callerId, ReadableMap dialOption) {
        if (mEnxRoom != null) {
            try {
                mEnxRoom.makeOutboundCall(number, callerId, EnxUtils.convertMapToJson(dialOption));
            } catch (JSONException exception) {
                exception.printStackTrace();
            }

        }
    }

    @ReactMethod
    public void cancelOutboundCall(String number) {
        if (mEnxRoom != null) {
            try {
                mEnxRoom.cancelOutboundCall(number);
            } catch (Exception exception) {
                exception.printStackTrace();
            }

        }
    }

    @ReactMethod
    public void getPlayer(String clientId, Promise promise) {
        if (mEnxRoom != null) {
            try {
                EnxPlayerView playerView = mEnxRoom.getPlayer(clientId);
                WritableMap map = Arguments.createMap();
                map.putString("playerId", String.valueOf(playerView.getId()));
                map.putString("clientId", clientId);
                // Add more data to map if needed
                promise.resolve(map);
            } catch (Exception exception) {
                exception.printStackTrace();
                promise.reject("ERROR", exception.getMessage());
            }
        } 
    }


    @ReactMethod
    public void changeBgColorForClients(ReadableArray clientIds, String color) {
        if (mEnxRoom != null) {
            try {
                ArrayList<String> idsList = new ArrayList<>();
                for (int i = 0; i < clientIds.size(); i++) {
                    idsList.add(clientIds.getString(i));
                }
                mEnxRoom.changeBgColorForClients(idsList, color);
            } catch (Exception exception) {
            }
        }
    }

    @ReactMethod
    public void highlightBorderForClient(ReadableArray clientIds) {
        if (mEnxRoom != null) {
            try {
                ArrayList<String> idsList = new ArrayList<>();
                for (int i = 0; i < clientIds.size(); i++) {
                    idsList.add(clientIds.getString(i));
                }
                mEnxRoom.highlightBorderForClient(idsList);
            } catch (Exception exception) {
            }
        }
    }

    @ReactMethod
    public void subscribeForLiveTranscription(Boolean enable) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.subscribeForLiveTranscription(enable);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void startLiveTranscriptionForRoom(String language) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.startLiveTranscriptionForRoom(language);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void stopLiveTranscription() {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.stopLiveTranscription();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void requestSharePermission(String enxPubType) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.requestSharePermission(EnxRoom.EnxPubType.valueOf(enxPubType));
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void cancelSharePermission(String enxPubType) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.cancelSharePermission(EnxRoom.EnxPubType.valueOf(enxPubType));
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void setSharePermissionMode(String enxPubType, String enxPubMode) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.setSharePermissionMode(EnxRoom.EnxPubType.valueOf(enxPubType), EnxRoom.EnxPubMode.valueOf(enxPubMode));
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void grantSharePermission(String enxPubType, String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.grantSharePermission(EnxRoom.EnxPubType.valueOf(enxPubType), clientId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void denySharePermission(String enxPubType, String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.denySharePermission(EnxRoom.EnxPubType.valueOf(enxPubType), clientId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void releaseSharePermission(String enxPubType, String clientId) {
        try {
            if (mEnxRoom != null) {
                mEnxRoom.releaseSharePermission(EnxRoom.EnxPubType.valueOf(enxPubType), clientId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @ReactMethod
    public void setCustomData(ReadableMap dataOptions,ReadableMap data){
        if (mEnxRoom != null) {
            try {
                mEnxRoom.setCustomData(EnxUtils.convertMapToJson(dataOptions),EnxUtils.convertMapToJson(data));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @ReactMethod
    public void getCustomData(ReadableMap jsonObject){
        if (mEnxRoom != null) {
            try {
                mEnxRoom.getCustomData(EnxUtils.convertMapToJson(jsonObject));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
    @ReactMethod
    public void saveCustomData(ReadableMap dataOptions, ReadableMap data){
        if (mEnxRoom != null) {
            try {
                mEnxRoom.saveCustomData(EnxUtils.convertMapToJson(dataOptions),EnxUtils.convertMapToJson(data));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

    }

    @ReactMethod
    public WritableMap getSharePermissions() {
        try {
            if (mEnxRoom != null) {

                return EnxUtils.jsonToReact(mEnxRoom.getSharePermissions());
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return null;
    }

    @Nonnull
    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public void onRoomConnected(EnxRoom enxRoom, JSONObject jsonObject) {

        mEnxRoom = enxRoom;
        WritableMap streamInfo = null;
        try {
            streamInfo = EnxUtils.jsonToReact(jsonObject);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomConnected", streamInfo);
        try {
            mEnxRoom.setActiveTalkerListObserver(this);
            mEnxRoom.setRecordingObserver(this);
            mEnxRoom.setScreenShareObserver(this);
            mEnxRoom.setTalkerObserver(this);
            mEnxRoom.setLogsObserver(this);
            mEnxRoom.setChairControlObserver(this);
            mEnxRoom.setMuteRoomObserver(this);
            mEnxRoom.setBandwidthObserver(this);
            mEnxRoom.setNetworkChangeObserver(this);
            mEnxRoom.setReconnectObserver(this);
            mEnxRoom.setCanvasObserver(this);
            mEnxRoom.setFileShareObserver(this);
            mEnxRoom.setLockRoomManagementObserver(this);
            mEnxRoom.setOutBoundCallObserver(this);
            mEnxRoom.setAnnotationObserver(this);
            mEnxRoom.setBreakoutRoomObserver(this);
            mEnxRoom.setEnxSwitchRoomObserver(this);
            mEnxRoom.setLiveRecordingObserver(this);
            mEnxRoom.setEnxRoomMuteUserObserver(this);
            mEnxRoom.setBandwidthObserver(this);
            mEnxRoom.setmEnxTranscriptionObserver(this);
            mEnxRoom.setEnxPermissionObserver(this);
            mEnxRoom.setEnxHlsObserver(this);
            enxRtc.setEnxTroubleShooterObserver(this);
            mEnxRoom.setLiveStreamingObserver(this);
            mEnxRoom.setEnxCustomDataStorageObserver(this);
            new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      if (!cameraPosition) {
                        localStream.switchCamera();
                      }
                      else{
                        localStream.mEnxPlayerView.setMirror(true);
                      }
                    }
                },500);

        } catch (Exception exception) {
            exception.printStackTrace();
        }

    }

    @Override
    public void onRoomError(JSONObject jsonObject) {
        try {
            ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
            for (String key : mLocalStream.keySet()) {
                EnxStream stream = mLocalStream.get(key);
                if (stream != null) {
                    stream.detachRenderer();
                }
            }
            ConcurrentHashMap<String, EnxStream> mRemoteStream = sharedState.getRemoteStream();
            for (String key : mRemoteStream.keySet()) {
                EnxStream stream = mRemoteStream.get(key);
                if (stream != null) {
                    stream.detachRenderer();
                }
            }
            if (mEnxRoom != null) {
                mEnxRoom = null;
            }
            if (enxRtc != null) {
                enxRtc = null;
            }
            try {
                sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomError", EnxUtils.jsonToReact(jsonObject));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUserConnected(JSONObject jsonObject) {
        try {

            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserConnected", EnxUtils.jsonToReact(jsonObject));

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUserDisConnected(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserDisConnected", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPublishedStream(EnxStream enxStream) {
        try {
            WritableMap streamInfo = EnxUtils.customJSONObject("The stream has been published.", "0", localStreamId);
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onPublishedStream", streamInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUnPublishedStream(EnxStream enxStream) {
    }

    @Override
    public void onStreamAdded(EnxStream enxStream) {
        try {
            ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
            mSubscriberStreams.put(enxStream.getId(), enxStream);
            WritableMap streamInfo = EnxUtils.prepareJSStreamMap(enxStream);
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStreamAdded", streamInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSubscribedStream(EnxStream enxStream) {
        try {
            ConcurrentHashMap<String, EnxStream> mSubscriberStreams = sharedState.getRemoteStream();
            mSubscriberStreams.put(enxStream.getId(), enxStream);
            WritableMap streamInfo = EnxUtils.prepareJSStreamMap(enxStream);
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSubscribedStream", streamInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUnSubscribedStream(EnxStream enxStream) {
    }

    @Override
    public void onRoomDisConnected(JSONObject jsonObject) {
        try {
            ConcurrentHashMap<String, EnxStream> mLocalStream = sharedState.getLocalStream();
            for (String key : mLocalStream.keySet()) {
                EnxStream stream = mLocalStream.get(key);
                if (stream != null) {
                    stream.detachRenderer();
                }
            }
            ConcurrentHashMap<String, EnxStream> mRemoteStream = sharedState.getRemoteStream();
            for (String key : mRemoteStream.keySet()) {
                EnxStream stream = mRemoteStream.get(key);
                if (stream != null) {
                    stream.detachRenderer();
                }
            }
            if (mEnxRoom != null) {
                mEnxRoom = null;
            }
            if (enxRtc != null) {
                enxRtc = null;
            }
            try {
                sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomDisConnected", EnxUtils.jsonToReact(jsonObject));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //boolean isFirst = true;
    @Override
    public void onActiveTalkerList(final List<EnxStream> list) {
        try {
            final JSONObject jsonObject = new JSONObject();
            JSONArray jsonArray = new JSONArray();
            tempAtList.clear();
            for (int i = 0; i < list.size(); i++) {
                EnxStream enxStream = list.get(i);
                tempAtList.add(enxStream);
                JSONObject object = new JSONObject();
                object.put("clientId", enxStream.getClientId());
                object.put("name", enxStream.getName());
                object.put("mediatype", enxStream.getMediaType());
                object.put("videoaspectratio", enxStream.getVideoAspectRatio());
                object.put("streamId", enxStream.getId());
                object.put("pinned", enxStream.isPinned());
                object.put("videomuted", !enxStream.isVideoActive());
                object.put("audiomuted", !enxStream.isAudioActive());
                jsonArray.put(object);
            }
            jsonObject.put("activeList", jsonArray);

            sendEventMapArray(this.getReactApplicationContext(), roomPreface + "onActiveTalkerList", EnxUtils.convertJsonToArray(jsonObject.optJSONArray("activeList")));
            /*if(isFirst){
                localStream.muteSelfAudio(isFirst);

            }*/
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onActiveTalkerList(List<EnxStream> list, EnxRoom enxRoom) {

    }

    @Override
    public void onEventError(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onEventError", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onEventInfo(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onEventInfo", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onNotifyDeviceUpdate(String s) {
        try {
            sendEventWithString(this.getReactApplicationContext(), roomPreface + "onNotifyDeviceUpdate", String.valueOf(s));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAcknowledgedSendData(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAcknowledgedSendData", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMessageReceived(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onMessageReceived", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUserDataReceived(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserDataReceived", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUserStartTyping(boolean b) {

    }



/*    @Override
    public void onUserStartTyping(boolean b) {

    }*/

    @Override
    public void onCanvasStarted(EnxStream enxStream) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("result", 0);
            jsonObject.put("name", enxStream.getName());
            jsonObject.put("clientId", enxStream.getClientId());
            jsonObject.put("streamId", enxStream.getId());

            sendEventMap(this.getReactApplicationContext(), roomPreface + "onCanvasStarted", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCanvasStopped(EnxStream enxStream) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("result", 0);
            jsonObject.put("name", enxStream.getName());
            jsonObject.put("clientId", enxStream.getClientId());
            jsonObject.put("streamId", enxStream.getId());

            ConcurrentHashMap<String, EnxPlayerView> mPlayers = sharedState.getPlayerView();
            if (mPlayers.containsKey(jsonObject.optString("streamId"))) {
                mPlayers.remove(jsonObject.optString("streamId"));
            }
            ConcurrentHashMap<String, FrameLayout> mLocalStreamViewContainers = sharedState.getStreamViewContainers();
            if (mLocalStreamViewContainers.containsKey(jsonObject.optString("streamId"))) {
                mLocalStreamViewContainers.remove(jsonObject.optString("streamId"));
            }

            sendEventMap(this.getReactApplicationContext(), roomPreface + "onCanvasStopped", EnxUtils.jsonToReact(jsonObject));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStartCanvasAck(JSONObject jsonObject) {

    }

    @Override
    public void onStoppedCanvasAck(JSONObject jsonObject) {

    }

 /*   @Override
    public void onSwitchedUserRole(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSwitchedUserRole", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUserRoleChanged(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserRoleChanged", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }*/

    @Override
    public void onConferencessExtended(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onConferencessExtended", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConferenceRemainingDuration(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onConferenceRemainingDuration", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckDropUser(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckDropUser", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckDestroy(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckDestroy", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAudioEvent(JSONObject jsonObject) {
        try {
           /* if(isFirst){
                isFirst = false;
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        localStream.muteSelfAudio(isFirst);
                    }
                },1000);

                return;
            }*/
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onAudioEvent", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onVideoEvent(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onVideoEvent", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedData(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onReceivedData", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRemoteStreamAudioMute(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onRemoteStreamAudioMute", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRemoteStreamAudioUnMute(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onRemoteStreamAudioUnMute", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRemoteStreamVideoMute(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onRemoteStreamVideoMute", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRemoteStreamVideoUnMute(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onRemoteStreamVideoUnMute", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStartRecordingEvent(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStartRecordingEvent", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRoomRecordingOn(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomRecordingOn", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStopRecordingEvent(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStopRecordingEvent", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRoomRecordingOff(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomRecordingOff", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStartScreenShareACK(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStartScreenShareACK", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStoppedScreenShareACK(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStoppedScreenShareACK", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onScreenSharedStarted(EnxStream enxStream) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("result", 0);
            jsonObject.put("name", enxStream.getName());
            jsonObject.put("clientId", enxStream.getClientId());
            jsonObject.put("streamId", enxStream.getId());

            sendEventMap(this.getReactApplicationContext(), roomPreface + "onScreenSharedStarted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onScreenSharedStopped(EnxStream enxStream) {

        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("result", 0);
            jsonObject.put("name", enxStream.getName());
            jsonObject.put("clientId", enxStream.getClientId());
            jsonObject.put("streamId", enxStream.getId());

            ConcurrentHashMap<String, EnxPlayerView> mPlayers = sharedState.getPlayerView();
            if (mPlayers.containsKey(jsonObject.optString("streamId"))) {
                mPlayers.remove(jsonObject.optString("streamId"));
            }
            ConcurrentHashMap<String, FrameLayout> mLocalStreamViewContainers = sharedState.getStreamViewContainers();
            if (mLocalStreamViewContainers.containsKey(jsonObject.optString("streamId"))) {
                mLocalStreamViewContainers.remove(jsonObject.optString("streamId"));
            }

            sendEventMap(this.getReactApplicationContext(), roomPreface + "onScreenSharedStopped", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSetTalkerCount(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSetTalkerCount", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onGetTalkerCount(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onGetTalkerCount", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMaxTalkerCount(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onMaxTalkerCount", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onLogUploaded(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onLogUploaded", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFloorRequested(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFloorRequested", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFloorRequestReceived(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFloorRequestReceived", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onProcessFloorRequested(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onProcessFloorRequested", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onGrantedFloorRequest(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onGrantedFloorRequest", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDeniedFloorRequest(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onDeniedFloorRequest", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReleasedFloorRequest(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onReleasedFloorRequest", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFloorCancelled(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFloorCancelled", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFloorFinished(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFloorFinished", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCancelledFloorRequest(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onCancelledFloorRequest", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFinishedFloorRequest(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFinishedFloorRequest", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onACKInviteToFloorRequested(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKInviteToFloorRequested", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onInviteToFloorRequested(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onInviteToFloorRequested", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onInvitedForFloorAccess(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onInvitedForFloorAccess", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCanceledFloorInvite(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onCanceledFloorInvite", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRejectedInviteFloor(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRejectedInviteFloor", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAcceptedFloorInvite(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAcceptedFloorInvite", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onHardMutedAudio(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onHardMutedAudio", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onHardUnMutedAudio(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onHardUnMutedAudio", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedHardMuteAudio(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onReceivedHardMuteAudio", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedHardUnMuteAudio(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onReceivedHardUnMuteAudio", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onHardMutedVideo(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onHardMutedVideo", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onHardUnMutedVideo(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onHardUnMutedVideo", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedHardMuteVideo(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onReceivedHardMuteVideo", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedHardUnMuteVideo(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onReceivedHardUnMuteVideo", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onHardMuted(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onHardMuted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedHardMute(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onReceivedHardMute", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onHardUnMuted(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onHardUnMuted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedHardUnMute(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onReceivedHardUnMute", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAcknowledgeStats(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAcknowledgeStats", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReceivedStats(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onReceivedStats", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPlayerStats(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), streamPreface + "onPlayerStats", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onBandWidthUpdated(JSONArray jsonArray) {
        try {
            sendEventMapArray(this.getReactApplicationContext(), roomPreface + "onBandWidthUpdated", EnxUtils.convertJsonToArray(jsonArray));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onShareStreamEvent(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onShareStreamEvent", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCanvasStreamEvent(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onCanvasStreamEvent", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectionInterrupted(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onConnectionInterrupted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectionLost(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onConnectionLost", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReconnect(String s) {
        sendEventWithString(this.getReactApplicationContext(), roomPreface + "onReconnect", String.valueOf(s));
    }

    @Override
    public void onUserReconnectSuccess(EnxRoom enxRoom, JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserReconnectSuccess", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void OnCapturedView(Bitmap bitmap) {
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            sendEventWithString(this.getReactApplicationContext(), roomPreface + "OnCapturedView", Base64.encodeToString(byteArray, Base64.DEFAULT));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAdvancedOptionsUpdate(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAdvancedOptionsUpdate", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onGetAdvancedOptions(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onGetAdvancedOptions", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPrivacyModeUpDated(JSONObject jsonObject) {
        //To Do later
    }

    @Override
    public void onFileUploadStarted(JSONObject jsonObject) {
        Log.e("onFileUploadStarted", jsonObject.toString());
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileUploadStarted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onInitFileUpload(JSONObject jsonObject) {
        try {
            Log.e("OnInitFileUpload", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onInitFileUpload", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileAvailable(JSONObject jsonObject) {

        try {
            Log.e("onFileAvailable", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileAvailable", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileUploaded(JSONObject jsonObject) {
        try {
            Log.e("onFileUploaded", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileUploaded", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileUploadCancelled(JSONObject jsonObject) {
        try {
            Log.e("onFileUploadCancelled", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileUploadCancelled", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileUploadFailed(JSONObject jsonObject) {
        try {
            Log.e("onFileUploadFailed", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileUploadFailed", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileDownloaded(JSONObject jsonObject) {
        try {
            Log.e("onFileDownloaded", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileDownloaded", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileDownloadCancelled(JSONObject jsonObject) {
        try {
            Log.e("onFileDownloadCancelled", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileDownloadCancelled", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileDownloadFailed(JSONObject jsonObject) {
        try {
            Log.e("onFileDownloadFailed", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFileDownloadFailed", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onInitFileDownload(JSONObject jsonObject) {
        try {
            Log.e("onInitFileDownload", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onInitFileDownload", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckLockRoom(JSONObject jsonObject) {
        try {
            Log.e("onAckLockRoom", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckLockRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckUnLockRoom(JSONObject jsonObject) {
        try {
            Log.e("onAckUnLockRoom", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckUnLockRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onLockedRoom(JSONObject jsonObject) {
        try {
            Log.e("onLockedRoom", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onLockedRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUnLockedRoom(JSONObject jsonObject) {
        try {
            Log.e("onUnLockedRoom", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUnLockedRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onOutBoundCallInitiated(JSONObject jsonObject) {
        try {
            Log.e("onOutBoundCallInitiated", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onOutBoundCallInitiated", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDialStateEvents(JSONObject jsonObject) {
        try {
            Log.e("onDialStateWithInfo", String.valueOf(jsonObject));
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onDialStateWithInfo", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception exception) {
            exception.printStackTrace();
        }

    }

    @Override
    public void onDialStateEvents(EnxRoom.EnxOutBoundCallState enxOutBoundCallState) {
        try {
            String state;
            String.valueOf(enxOutBoundCallState);
            state = enxOutBoundCallState.name();
            Log.e("onDialStateEventsJava", state);
            sendEventWithString(this.getReactApplicationContext(), roomPreface + "onDialStateEvents", state);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onDTMFCollected(String s) {
        try {
            sendEventWithString(this.getReactApplicationContext(), roomPreface + "onDTMFCollected", s);
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }


    @Override
    public void onOutBoundCallCancel(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onOutBoundCallCancel", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onOutBoundCallSendDtmf(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onOutBoundCallSendDtmf", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onAckPinUsers(JSONObject jsonObject) {
        try {
            Log.e("onAckPinUsers", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckPinUsers", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckUnpinUsers(JSONObject jsonObject) {
        try {
            Log.e("onAckUnpinUsers", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckUnpinUsers", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPinnedUsers(JSONObject jsonObject) {
        try {
            Log.e("onPinnedUsers", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onPinnedUsers", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onRoomAwaited(EnxRoom enxRoom, JSONObject jsonObject) {
        try {
            Log.e("onRoomAwaited", jsonObject.toString());
            mEnxRoom = enxRoom;
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomAwaited", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUserAwaited(JSONObject jsonObject) {
        try {
            Log.e("onUserAwaited", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserAwaited", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckForApproveAwaitedUser(JSONObject jsonObject) {
        try {
            Log.e("onAckForApproveAwaited", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckForApproveAwaitedUser", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckForDenyAwaitedUser(JSONObject jsonObject) {
        try {
            Log.e("onAckForDenyAwaitedUser", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckForDenyAwaitedUser", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckAddSpotlightUsers(JSONObject jsonObject) {
        try {
            Log.e("onAckAddSpotlightUsers", jsonObject.toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckAddSpotlightUsers", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAckRemoveSpotlightUsers(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckRemoveSpotlightUsers", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUpdateSpotlightUsers(JSONObject jsonObject) {
        Log.e("onUpdateSpotlightUsers", jsonObject.toString());
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUpdateSpotlightUsers", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRoomBandwidthAlert(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomBandwidthAlert", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStopAllSharingACK(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStopAllSharingACK", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKStartLiveTranscription(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKStartLiveTranscription", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKStopLiveTranscription(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKStopLiveTranscription", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKSubscribeForLiveTranscription(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKSubscribeForLiveTranscription", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onTranscriptionEvents(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onTranscriptionEvents", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onRoomTranscriptionOn(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomTranscriptionOn", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onRoomTranscriptionOff(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomTranscriptionOff", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSelfTranscriptionOn(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSelfTranscriptionOn", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSelfTranscriptionOff(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSelfTranscriptionOff", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    private JSONObject getLocalStreamJsonObject(ReadableMap localStreamInfo) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("audio", localStreamInfo.getBoolean("audio"));
            jsonObject.put("video", localStreamInfo.getBoolean("video"));
            jsonObject.put("data", localStreamInfo.getBoolean("data"));
            jsonObject.put("maxVideoBW", localStreamInfo.getString("maxVideoBW"));
            jsonObject.put("minVideoBW", localStreamInfo.getString("minVideoBW"));
            JSONObject videoSize = new JSONObject();
            videoSize.put("minWidth", localStreamInfo.getString("minWidth"));
            videoSize.put("minHeight", localStreamInfo.getString("minHeight"));
            videoSize.put("maxWidth", localStreamInfo.getString("maxWidth"));
            videoSize.put("maxHeight", localStreamInfo.getString("maxHeight"));
            jsonObject.put("videoSize", videoSize);
            jsonObject.put("audioMuted", localStreamInfo.getBoolean("audioMuted"));
            jsonObject.put("videoMuted", localStreamInfo.getBoolean("videoMuted"));
            jsonObject.put("name", localStreamInfo.getString("name"));
            return jsonObject;
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    private JSONObject getRoomInfoObject(ReadableMap roomInfo) {
        try {
            JSONObject jsonObject = new JSONObject();

            jsonObject.put("allow_reconnect", roomInfo.getBoolean("allow_reconnect"));
            jsonObject.put("number_of_attempts", roomInfo.getString("number_of_attempts"));
            jsonObject.put("timeout_interval", roomInfo.getString("timeout_interval"));
            return jsonObject;
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    private JSONObject getAdvancedOptionsObject(JSONArray advanceOptions) {

        try {
            Log.e("getAdvancedOptions", advanceOptions.toString());
//        [{"battery_updates":false},{"notify_video_resolution_change":false}]
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("options", advanceOptions);
            return jsonObject;
        } catch (JSONException e) {
            e.printStackTrace();
        }


        return null;
    }

    private JSONObject getEventObject(String eventName, boolean value) {

        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", eventName);
            jsonObject.put("enable", value);
            return jsonObject;
        } catch (JSONException e) {

        }

        return null;
    }

    private static boolean contains(ArrayList array, String value) {
        try {
            for (int i = 0; i < array.size(); i++) {
                if (array.get(i).equals(value)) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private void sendEventMapArray(ReactContext reactContext, String eventName, @Nullable WritableArray eventData) {
        try {
            if (contains(jsEvents, eventName) || contains(componentEvents, eventName)) {
                reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                        .emit(eventName, eventData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendEventMap(ReactContext reactContext, String eventName, @Nullable WritableMap eventData) {
        try {
            if (contains(jsEvents, eventName) || contains(componentEvents, eventName)) {
                reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                        .emit(eventName, eventData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendEventWithString(ReactContext reactContext, String eventName, String eventString) {
        try {
            if (contains(jsEvents, eventName) || contains(componentEvents, eventName)) {
                reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                        .emit(eventName, eventString);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onAnnotationStarted(EnxStream enxStream) {
        try {
            WritableMap streamInfo = EnxUtils.customJSONObject("Annotation has been started.", "0", enxStream.getId().toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAnnotationStarted", streamInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override

    public void onStartAnnotationAck(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStartAnnotationAck", EnxUtils.jsonToReact(jsonObject));
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (tempAtList != null) {
                        EnxStream stream = createDemyStream();
                        if (stream != null) {
                            tempAtList.add(tempAtList.size(), stream);
                        }
                        takeAtList(tempAtList);
                        updateATView();
                    }
                    handler.removeCallbacks(this);
                }
            }, 100);
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    private void updateATView() {

        try {
            final Handler handler1 = new Handler();

            handler1.postDelayed(new Runnable() {

                @Override

                public void run() {
                    if (tempAtList != null) {
                        tempAtList.remove(tempAtList.size() - 1);
                        takeAtList(tempAtList);
                    }

                    handler1.removeCallbacks(this);

                }

            }, 500);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private EnxStream createDemyStream() {

        try {
            EnxStream teamStream = null;

            ConcurrentHashMap<String, EnxStream> mEnxStream = sharedState.getRemoteStream();

            for (String key : mEnxStream.keySet()) {

                EnxStream remoteStream = mEnxStream.get(key);

                if (!tempAtList.contains(remoteStream)) {

                    teamStream = remoteStream;

                    break;

                }

            }

            return teamStream;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

//Demo Notification

    private void takeAtList(List<EnxStream> alist) {

        try {

            //Toast.makeText(mReactContext,"AT List " +alist.size(),Toast.LENGTH_LONG).show();

            final JSONObject jsonObject = new JSONObject();

            JSONArray jsonArray = new JSONArray();

            for (int i = 0; i < alist.size(); i++) {

                EnxStream enxStream = alist.get(i);

                JSONObject object = new JSONObject();

                object.put("clientId", enxStream.getClientId());

                object.put("name", enxStream.getName());

                object.put("mediatype", enxStream.getMediaType());

                object.put("videoaspectratio", enxStream.getVideoAspectRatio());

                object.put("streamId", enxStream.getId());

                object.put("pinned", enxStream.isPinned());

                object.put("videomuted", !enxStream.isVideoActive());

                object.put("audiomuted", !enxStream.isAudioActive());

                jsonArray.put(object);

            }

            jsonObject.put("activeList", jsonArray);

            sendEventMapArray(this.getReactApplicationContext(), roomPreface + "onActiveTalkerList", EnxUtils.convertJsonToArray(jsonObject.optJSONArray("activeList")));

        } catch (Exception e) {

            e.printStackTrace();

        }

    }


    @Override
    public void onAnnotationStopped(EnxStream enxStream) {
        try {
            WritableMap streamInfo = EnxUtils.customJSONObject("Annotation has been stopped.", "0", enxStream.getId().toString());
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAnnotationStopped", streamInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onStoppedAnnotationAck(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStoppedAnnotationAck", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    // Call Back functions of EnxTalkerNotificationObserver
    @Override
    public void onAckSubscribeTalkerNotification(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckSubscribeTalkerNotification", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onAckUnsubscribeTalkerNotification(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckUnsubscribeTalkerNotification", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onTalkerNtification(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onTalkerNtification", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onAckCreateBreakOutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckCreateBreakOutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            Log.e("Exception", "onAckCreateBreakOutRoom" + exception.getMessage());
        }
    }

    @Override
    public void onAckCreateAndInviteBreakOutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckCreateAndInviteBreakOutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {

        }
    }

    @Override
    public void onAckInviteBreakOutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckInviteBreakOutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {

        }
    }

    @Override
    public void onAckPause(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckPause", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {

        }
    }

    @Override
    public void onAckResume(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckResume", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {

        }
    }

    @Override
    public void onAckMuteRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckMuteRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {

        }
    }

    @Override
    public void onAckUnmuteRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckUnmuteRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {

        }
    }

    @Override
    public void onUserPaused(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserPaused", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {

        }
    }

    @Override
    public void onUserResumed(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserResumed", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onFailedJoinBreakOutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onFailedJoinBreakOutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onConnectedBreakoutRoom(EnxRoom enxRoom, JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onConnectedBreakoutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();

        }
    }

    @Override
    public void onDisconnectedBreakoutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onDisconnectedBreakoutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onUserJoinedBreakoutRoom(EnxRoom enxRoom, JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserJoinedBreakoutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }


    @Override
    public void onInvitationForBreakoutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onInvitationForBreakoutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onDestroyedBreakoutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onDestroyedBreakoutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onUserDisconnectedFromBreakoutRoom(EnxRoom enxRoom, JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onUserDisconnectedFromBreakoutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }


    @Override
    public void onAckRejectBreakOutRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckRejectBreakOutRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onBreakoutRoomCreated(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onBreakoutRoomCreated", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onBreakoutRoomInvited(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onBreakoutRoomInvited", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onBreakoutRoomInviteRejected(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onBreakoutRoomInviteRejected", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onBreakoutroomjoining(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onBreakoutroomjoining", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onClientDiagnosisFailed(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onClientDiagnosisFailed", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onClientDiagnosisStopped(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onClientDiagnosisStopped", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }


    @Override
    public void onClientDiagnosisFinished(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onClientDiagnosisFinished", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onClientDiagnosisStatus(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onClientDiagnosisStatus", EnxUtils.jsonToReact(jsonObject));
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onAckSwitchedRoom(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckSwitchedRoom", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onRoomModeSwitched(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onRoomModeSwitched", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }


    @Override
    public void onACKStartLiveRecording(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKStartLiveRecording", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKStopLiveRecording(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKStopLiveRecording", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onRoomLiveRecordingOn(JSONObject jsonObject) {

    }

    @Override
    public void onRoomLiveRecordingOff(JSONObject jsonObject) {

    }

    @Override
    public void onRoomLiveRecordingFailed(JSONObject jsonObject) {

    }

    @Override
    public void onRoomLiveRecordingUpdate(JSONObject jsonObject) {

    }

    /*@Override
    public void onLiveRecordingNotification(JSONObject jsonObject) {

    }

    @Override
    public void onRoomliverecordOn(JSONObject jsonObject) {

    }*/


    @Override
    public void onAckHardMuteUserAudio(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckHardMuteUserAudio", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onAckHardunMuteUserAudio(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckHardunMuteUserAudio", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onAckHardMuteUserVideo(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckHardMuteUserVideo", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onAckHardUnMuteUserVideo(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckHardUnMuteUserVideo", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSharePermissionsModeChanged(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSharePermissionsModeChanged", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKSetSharePermissionMode(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKSetSharePermissionMode", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKGrantSharePermission(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKGrantSharePermission", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKDenySharePermission(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKDenySharePermission", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKReleaseSharePermission(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKReleaseSharePermission", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKRequestSharePermission(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKRequestSharePermission", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKCancelSharePermission(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKCancelSharePermission", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSharePermissionRequested(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSharePermissionRequested", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSharePermissionReleased(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSharePermissionReleased", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSharePermissionDeny(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSharePermissionDeny", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSharePermissionCanceled(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSharePermissionCanceled", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onSharePermissionGranted(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onSharePermissionGranted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onHlsStarted(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onHlsStarted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }

    }

    @Override
    public void onHlsStopped(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onHlsStopped", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }

    }

    @Override
    public void onHlsFailed(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onHlsFailed", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }

    }

    @Override
    public void onHlsWaiting(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onHlsWaiting", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }

    }

    @Override
    public void onAckStartStreaming(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckStartStreaming", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onAckStopStreaming(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onAckStopStreaming", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onStreamingStarted(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStreamingStarted", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onStreamingStopped(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStreamingStopped", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onStreamingFailed(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStreamingFailed", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onStreamingUpdated(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onStreamingUpdated", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onCustomDataSaved(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onCustomDataSaved", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onGetCustomData(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onGetCustomData", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onCustomDataUpdated(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onCustomDataUpdated", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    public void onACKCustomDataUpdated(JSONObject jsonObject) {
        try {
            sendEventMap(this.getReactApplicationContext(), roomPreface + "onACKCustomDataUpdated", EnxUtils.jsonToReact(jsonObject));
        } catch (JSONException exception) {
            exception.printStackTrace();
        }
    }
}
