package com.mappls.sdk.intouch.reactnative;

import androidx.annotation.NonNull;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
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.ReadableMapKeySetIterator;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.google.gson.Gson;
import com.mappls.sdk.intouch.InTouch;
import com.mappls.sdk.intouch.alarms.vo.CreateAlarmResponse;
import com.mappls.sdk.intouch.alarms.vo.alarmconfig.InTouchAlarmResponse;
import com.mappls.sdk.intouch.alarms.vo.alarmlogs.InTouchAlarmLogsResponse;
import com.mappls.sdk.intouch.api.drives.model.IntouchDriveResponse;
import com.mappls.sdk.intouch.api.geofence.GeoFencePoint;
import com.mappls.sdk.intouch.api.geofence.create.model.CreateGeoFenceResponse;
import com.mappls.sdk.intouch.api.geofence.list.model.InTouchGeoFenceResponse;
import com.mappls.sdk.intouch.api.geofence.update.model.UpdateGeoFenceResponse;
import com.mappls.sdk.intouch.api.getdevices.model.DevicesResponse;
import com.mappls.sdk.intouch.api.locationevents.model.LocationEventsResponse;
import com.mappls.sdk.intouch.callbacks.ICreateAlarmListener;
import com.mappls.sdk.intouch.callbacks.ICreateGeoFenceListener;
import com.mappls.sdk.intouch.callbacks.ICreateTripListener;
import com.mappls.sdk.intouch.callbacks.IDeviceInfoListener;
import com.mappls.sdk.intouch.callbacks.IDeviceListener;
import com.mappls.sdk.intouch.callbacks.IDrivesListener;
import com.mappls.sdk.intouch.callbacks.IGeoFenceActivityListener;
import com.mappls.sdk.intouch.callbacks.IGetAlarmsListener;
import com.mappls.sdk.intouch.callbacks.IGetAlarmsLogsListener;
import com.mappls.sdk.intouch.callbacks.IGetGeoFenceListener;
import com.mappls.sdk.intouch.callbacks.IGetTripsListener;
import com.mappls.sdk.intouch.callbacks.ILocationEventsListener;
import com.mappls.sdk.intouch.callbacks.IResultListener;
import com.mappls.sdk.intouch.callbacks.ITripInfoListener;
import com.mappls.sdk.intouch.callbacks.IUpdateAlarmListener;
import com.mappls.sdk.intouch.callbacks.IUpdateGeoFenceListener;
import com.mappls.sdk.intouch.common.Geometry;
import com.mappls.sdk.intouch.devices.deviceInfo.DeviceInfoResponse;
import com.mappls.sdk.intouch.geofence.vo.activity.GeoFenceActivityResponse;
import com.mappls.sdk.intouch.trips.vo.trip.TripInfoResponse;
import com.mappls.sdk.intouch.trips.vo.trip.TripsResponse;
import com.mappls.sdk.intouch.trips.vo.triprequest.TripDestination;
import com.mappls.sdk.intouch.trips.vo.triprequest.TripGeofence;
import com.mappls.sdk.services.account.MapplsAccountManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class MapplsIntouchApiModule extends ReactContextBaseJavaModule {

    public static final String TAG = MapplsIntouchModule.class.getSimpleName();
    private final ReactApplicationContext reactContext;

    public MapplsIntouchApiModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

   /* @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put("DEFAULT_EVENT_NAME",Constants);
        return constants;
    }
*/
    public static WritableMap jsonToReact(JSONObject jsonObject) throws JSONException {
        WritableMap writableMap = Arguments.createMap();
        Iterator iterator = jsonObject.keys();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            Object value = jsonObject.get(key);
            if (value instanceof Float || value instanceof Double) {
                writableMap.putDouble(key, jsonObject.getDouble(key));
            } else if (value instanceof Number) {
                writableMap.putInt(key, jsonObject.getInt(key));
            } else if (value instanceof String) {
                writableMap.putString(key, jsonObject.getString(key));
            } else if (value instanceof JSONObject) {
                writableMap.putMap(key, jsonToReact(jsonObject.getJSONObject(key)));
            } else if (value instanceof JSONArray) {
                writableMap.putArray(key, jsonToReact(jsonObject.getJSONArray(key)));
            } else if (value == JSONObject.NULL) {
                writableMap.putNull(key);
            }
        }
        return writableMap;
    }

    public static WritableArray jsonToReact(JSONArray jsonArray) throws JSONException {
        WritableArray writableArray = Arguments.createArray();
        for (int i = 0; i < jsonArray.length(); i++) {
            Object value = jsonArray.get(i);
            if (value instanceof Float || value instanceof Double) {
                writableArray.pushDouble(jsonArray.getDouble(i));
            } else if (value instanceof Number) {
                writableArray.pushInt(jsonArray.getInt(i));
            } else if (value instanceof String) {
                writableArray.pushString(jsonArray.getString(i));
            } else if (value instanceof JSONObject) {
                writableArray.pushMap(jsonToReact(jsonArray.getJSONObject(i)));
            } else if (value instanceof JSONArray) {
                writableArray.pushArray(jsonToReact(jsonArray.getJSONArray(i)));
            } else if (value == JSONObject.NULL) {
                writableArray.pushNull();
            }
        }
        return writableArray;
    }

    @NonNull
    @Override
    public String getName() {
        return "MapplsIntouchApi";
    }

    @ReactMethod
    public void initializeApisSdk(ReadableMap map) {
        MapplsAccountManager.getInstance().setAtlasClientId(map.getString("clientId"));
        MapplsAccountManager.getInstance().setAtlasClientSecret(map.getString("clientSecret"));
        MapplsAccountManager.getInstance().setRestAPIKey(map.getString("restAPIKey"));
        MapplsAccountManager.getInstance().setMapSDKKey(map.getString("mapSDKKey"));
    }

    @ReactMethod
    public void getDevices(final ReadableMap map, final Promise promise) {
        if (map.hasKey("deviceIds") && !map.isNull("deviceIds")) {
            Long[] deviceIds = getLongList(map.getArray("deviceIds"));
            boolean includeInActive = map.hasKey("includeInActive") && map.getBoolean("includeInActive");
            boolean ignoreBeacon = map.hasKey("ignoreBeacon") && map.getBoolean("ignoreBeacon");
            Long lastUpdateTime = (long) map.getDouble("lastUpdateTime");


            InTouch.getDevices(deviceIds, includeInActive, ignoreBeacon, lastUpdateTime, new IDeviceListener() {
                @Override
                public void onSuccess(DevicesResponse devicesResponse) {

                    String deviceResponseJsonString = new Gson().toJsonTree(devicesResponse, DevicesResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(deviceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }

                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getDevices Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            boolean includeInActive = map.hasKey("includeInActive") && map.getBoolean("includeInActive");
            boolean ignoreBeacon = map.hasKey("ignoreBeacon") && map.getBoolean("ignoreBeacon");
            Long lastUpdateTime = (long) map.getDouble("lastUpdateTime");
            InTouch.getDevices(includeInActive, ignoreBeacon, lastUpdateTime, new IDeviceListener() {
                @Override
                public void onSuccess(DevicesResponse devicesResponse) {
                    String deviceResponseJsonString = new Gson().toJsonTree(devicesResponse, DevicesResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(deviceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getDevices Error: ",s + " " + s1 + " " + s2);
                }
            });

        }
    }

    @ReactMethod
    public void getDevice(final ReadableMap map, final Promise promise) {
        if (map.hasKey("deviceId") && map.hasKey("lastUpdateTime") && !map.isNull("lastUpdateTime") && !map.isNull("deviceId")) {
            Long lastUpdateTime = (long) map.getDouble("lastUpdateTime");
            Long deviceId = (long) map.getDouble("deviceId");
            InTouch.getDevice(deviceId, lastUpdateTime, new IDeviceListener() {
                @Override
                public void onSuccess(DevicesResponse devicesResponse) {
                    String deviceResponseJsonString = new Gson().toJsonTree(devicesResponse, DevicesResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(deviceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getDevices Error: ",s + " " + s1 + " " + s2);
                }
            });

        } else {
            promise.reject("getDevice Error: ", "provide all params");
        }
    }

    @ReactMethod
    public void getDevicesInfo(final ReadableMap map, final Promise promise) {

        if (map.hasKey("deviceIds") && !map.isNull("deviceIds")) {
            Long[] deviceIds = getLongList(map.getArray("deviceIds"));

            InTouch.getDevicesInfo(deviceIds, new IDeviceInfoListener() {
                @Override
                public void onSuccess(DeviceInfoResponse deviceInfoResponse) {
                    String deviceInfoResponseJsonString = new Gson().toJsonTree(deviceInfoResponse, DeviceInfoResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(deviceInfoResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getDeviceInfo Error: ",s + " " + s1 + " " + s2);
                }
            });
        } else {
            InTouch.getDevicesInfo(new IDeviceInfoListener() {
                @Override
                public void onSuccess(DeviceInfoResponse deviceInfoResponse) {
                    String deviceInfoResponseJsonString = new Gson().toJsonTree(deviceInfoResponse, DeviceInfoResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(deviceInfoResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getDeviceInfo Error: ",s + " " + s1 + " " + s2);
                }
            });
        }

    }

    @ReactMethod
    public void getLocationsEvents(final ReadableMap map, final Promise promise) {

        if (map.hasKey("deviceId") && !map.isNull("deviceId") && map.hasKey("startTime") && !map.isNull("startTime") && map.hasKey("endTime") && !map.isNull("endTime") && map.hasKey("skipPeriod") && !map.isNull("skipPeriod")) {
            long deviceId = (long) map.getDouble("deviceId");
            long startTime = (long) map.getDouble("startTime");
            long endTime = (long) map.getDouble("endTime");
            int skipPeriod = map.getInt("skipPeriod");

            InTouch.getLocationsEvents(deviceId, startTime, endTime, skipPeriod, new ILocationEventsListener() {
                @Override
                public void onSuccess(LocationEventsResponse locationEventsResponse) {
                    String locationEventsResponseJsonString = new Gson().toJsonTree(locationEventsResponse, LocationEventsResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(locationEventsResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getLocationsEvents Error: ",s + " " + s1 + " " + s2);
                }
            });

        } else {
            promise.reject("getLocationsEvents Error: ", "provide all params");
        }


    }

    @ReactMethod
    public void getDrive(final ReadableMap map, final Promise promise) {
        if (map.hasKey("deviceId") && !map.isNull("deviceId") && map.hasKey("startTime") && !map.isNull("startTime") && map.hasKey("endTime") && !map.isNull("endTime")) {
            long deviceId = (long) map.getDouble("deviceId");
            long startTime = (long) map.getDouble("startTime");
            long endTime = (long) map.getDouble("endTime");

            InTouch.getDrive(deviceId, startTime, endTime, new IDrivesListener() {
                @Override
                public void onSuccess(IntouchDriveResponse intouchDriveResponse) {
                    String intouchDriveResponseJsonString = new Gson().toJsonTree(intouchDriveResponse, IntouchDriveResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchDriveResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getDrive Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else {
            promise.reject("getDrive Error: ", "provide all params");
        }

    }


    @ReactMethod
    public void createGeoFence(final ReadableMap map, final Promise promise) {

        if (map.hasKey("geofenceName") && !map.isNull("geofenceName") && map.hasKey("geofencePoints") && !map.isNull("geofencePoints")) {

            String geofenceName = map.getString("geofenceName");
            ReadableArray geofencePoints = map.getArray("geofencePoints");
            InTouch.createGeoFence(geofenceName, createGeofencePointList(geofencePoints), new ICreateGeoFenceListener() {
                @Override
                public void onSuccess(CreateGeoFenceResponse createGeoFenceResponse) {
                    String createGeofenceResponseJsonString = new Gson().toJsonTree(createGeoFenceResponse, CreateGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(createGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("createGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else if (map.hasKey("geofenceName") && !map.isNull("geofenceName") && map.hasKey("geofencePoint") && !map.isNull("geofencePoint") && map.hasKey("range") && !map.isNull("range")) {
            String geofenceName = map.getString("geofenceName");
            GeoFencePoint geofencePoint = new GeoFencePoint(map.getArray("geofencePoint").getDouble(0), map.getArray("geofencePoint").getDouble(1));
            int range = map.getInt("range");

            InTouch.createGeoFence(geofenceName, geofencePoint, range, new ICreateGeoFenceListener() {
                @Override
                public void onSuccess(CreateGeoFenceResponse createGeoFenceResponse) {
                    String createGeofenceResponseJsonString = new Gson().toJsonTree(createGeoFenceResponse, CreateGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(createGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("createGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("geofenceName") && !map.isNull("geofenceName") && map.hasKey("geofencePoint") && !map.isNull("geofencePoint")) {
            String geofenceName = map.getString("geofenceName");
            GeoFencePoint geofencePoint = new GeoFencePoint(map.getArray("geofencePoint").getDouble(0), map.getArray("geofencePoint").getDouble(1));

            InTouch.createGeoFence(geofenceName, geofencePoint, new ICreateGeoFenceListener() {
                @Override
                public void onSuccess(CreateGeoFenceResponse createGeoFenceResponse) {
                    String createGeofenceResponseJsonString = new Gson().toJsonTree(createGeoFenceResponse, CreateGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(createGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("createGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("createGeofence Error: ", "please provide params");
        }
    }

    @ReactMethod
    public void getGeoFences(final ReadableMap map, final Promise promise) {
        if (map.hasKey("geofenceIds") && !map.isNull("geofenceIds") && map.hasKey("ignoreGeometry") && !map.isNull("ignoreGeometry")) {
            Long[] geofenceIds = getLongList(map.getArray("geofenceIds"));
            boolean ignoreGeometry = map.getBoolean("ignoreGeometry");

            InTouch.getGeoFences(geofenceIds, ignoreGeometry, new IGetGeoFenceListener() {
                @Override
                public void onSuccess(InTouchGeoFenceResponse inTouchGeoFenceResponse) {
                    String intouchGeoFenceGeofenceResponseJsonString = new Gson().toJsonTree(inTouchGeoFenceResponse, InTouchGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchGeoFenceGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("geofenceId") && !map.isNull("geofenceId") && map.hasKey("ignoreGeometry") && !map.isNull("ignoreGeometry")) {

            long geofenceId = (long) map.getDouble("geofenceId");
            boolean ignoreGeometry = map.getBoolean("ignoreGeometry");

            InTouch.getGeoFences(geofenceId, ignoreGeometry, new IGetGeoFenceListener() {
                @Override
                public void onSuccess(InTouchGeoFenceResponse inTouchGeoFenceResponse) {
                    String intouchGeoFenceGeofenceResponseJsonString = new Gson().toJsonTree(inTouchGeoFenceResponse, InTouchGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchGeoFenceGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else if (map.hasKey("ignoreGeometry") && !map.isNull("ignoreGeometry")) {
            boolean ignoreGeometry = map.getBoolean("ignoreGeometry");

            InTouch.getGeoFences(ignoreGeometry, new IGetGeoFenceListener() {
                @Override
                public void onSuccess(InTouchGeoFenceResponse inTouchGeoFenceResponse) {
                    String intouchGeoFenceGeofenceResponseJsonString = new Gson().toJsonTree(inTouchGeoFenceResponse, InTouchGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchGeoFenceGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("getGeofence Error: ", "Please provide required params");
        }

    }

    @ReactMethod
    public void updateGeoFence(final ReadableMap map, final Promise promise) {

        if (map.hasKey("geofenceId") && !map.isNull("geofenceId") && map.hasKey("geofenceName") && !map.isNull("geofenceName") && map.hasKey("geofencePoint") && !map.isNull("geofencePoint") && map.hasKey("buffer") && !map.isNull("buffer")) {
            long geofenceId = (long) map.getDouble("geofenceId");
            String geofenceName = map.getString("geofenceName");
            GeoFencePoint geoFencePoint = new GeoFencePoint(map.getArray("geofencePoint").getDouble(0), map.getArray("geofencePoint").getDouble(1));
            int buffer = map.getInt("buffer");
            InTouch.updateGeoFence(geofenceId, geofenceName, geoFencePoint, buffer, new IUpdateGeoFenceListener() {
                @Override
                public void onSuccess(UpdateGeoFenceResponse updateGeoFenceResponse) {

                    promise.resolve(updateGeoFenceResponse.getStatus());
//                    String updateGeoFenceGeofenceResponseJsonString = new Gson().toJsonTree(updateGeoFenceResponse, UpdateGeoFenceResponse.class).toString();
//                    try {
//                        promise.resolve(jsonToReact(new JSONObject(updateGeoFenceGeofenceResponseJsonString)));
//                    } catch (JSONException e) {
//                        promise.reject(e.getMessage(), e.getLocalizedMessage());
//                        e.printStackTrace();
//                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("updateGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("geofenceId") && !map.isNull("geofenceId") && map.hasKey("geofenceName") && !map.isNull("geofenceName") && map.hasKey("geofencePoints") && !map.isNull("geofencePoints")) {

            long geofenceId = (long) map.getDouble("geofenceId");
            String geofenceName = map.getString("geofenceName");
            List<GeoFencePoint> geoFencePoints = createGeofencePointList(map.getArray("geofencePoints"));
            InTouch.updateGeoFence(geofenceId, geofenceName, geoFencePoints, new IUpdateGeoFenceListener() {
                @Override
                public void onSuccess(UpdateGeoFenceResponse updateGeoFenceResponse) {
                    String updateGeoFenceGeofenceResponseJsonString = new Gson().toJsonTree(updateGeoFenceResponse, UpdateGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(updateGeoFenceGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("updateGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else if (map.hasKey("geofenceId") && !map.isNull("geofenceId") && map.hasKey("geofenceName") && !map.isNull("geofenceName") && map.hasKey("geofencePoint") && !map.isNull("geofencePoint")) {
            long geofenceId = (long) map.getDouble("geofenceId");
            String geofenceName = map.getString("geofenceName");
            GeoFencePoint geoFencePoint = new GeoFencePoint(map.getArray("geofencePoint").getDouble(0), map.getArray("geofencePoint").getDouble(1));
            InTouch.updateGeoFence(geofenceId, geofenceName, geoFencePoint, new IUpdateGeoFenceListener() {
                @Override
                public void onSuccess(UpdateGeoFenceResponse updateGeoFenceResponse) {
                    String updateGeoFenceGeofenceResponseJsonString = new Gson().toJsonTree(updateGeoFenceResponse, UpdateGeoFenceResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(updateGeoFenceGeofenceResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("updateGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("updateGeofence Error: ", "Please provide required params");
        }

    }

    @ReactMethod
    public void deleteGeoFence(final ReadableMap map, final Promise promise) {

        if (map.hasKey("geofenceIds") && !map.isNull("geofenceIds")) {
            Long[] geofenceIds = getLongList(map.getArray("geofenceIds"));
            InTouch.deleteGeoFence(geofenceIds, new IResultListener() {
                @Override
                public void onSuccess() {
                    promise.resolve("success");
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("deleteGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else if (map.hasKey("geofenceId") && !map.isNull("geofenceId")) {
            long geofenceId = (long) map.getDouble("geofenceId");
            InTouch.deleteGeoFence(geofenceId, new IResultListener() {
                @Override
                public void onSuccess() {
                    promise.resolve("success");
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("deleteGeofence Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("deleteGeofence Error: ", "Please provide required params");
        }

    }

    @ReactMethod
    public void getGeoFenceActivity(final ReadableMap map, final Promise promise) {
        if (map.hasKey("devicesIds") && !map.isNull("devicesIds") && map.hasKey("geofenceIds") && !map.isNull("geofenceIds") && map.hasKey("startTime") && !map.isNull("startTime") && map.hasKey("endTime") && !map.isNull("endTime")) {
            Long[] deviceIds = getLongList(map.getArray("devicesIds"));
            Long[] geofenceIds = getLongList(map.getArray("geofenceIds"));
            long startTime = (long) map.getDouble("startTime");
            long endTime = (long) map.getDouble("endTime");
            InTouch.getGeoFenceActivity(deviceIds, geofenceIds, startTime, endTime, new IGeoFenceActivityListener() {
                @Override
                public void onSuccess(GeoFenceActivityResponse geoFenceActivityResponse) {
                    String geoFenceActivityResponseJsonString = new Gson().toJsonTree(geoFenceActivityResponse, GeoFenceActivityResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(geoFenceActivityResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("GeoFenceActivity Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("devicesIds") && !map.isNull("devicesIds") && map.hasKey("startTime") && !map.isNull("startTime") && map.hasKey("endTime") && !map.isNull("endTime")) {
            Long[] deviceIds = getLongList(map.getArray("devicesIds"));
            long startTime = (long) map.getDouble("startTime");
            long endTime = (long) map.getDouble("endTime");
            InTouch.getGeoFenceActivity(deviceIds, startTime, endTime, new IGeoFenceActivityListener() {
                @Override
                public void onSuccess(GeoFenceActivityResponse geoFenceActivityResponse) {
                    String geoFenceActivityResponseJsonString = new Gson().toJsonTree(geoFenceActivityResponse, GeoFenceActivityResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(geoFenceActivityResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("GeoFenceActivity Error: ", s + " " + s1 + " " + s2);
                }
            });


        } else {
            promise.reject("GeoFenceActivity Error: ", "Please provide required params");
        }

    }

    //Todo: implement this method
    @ReactMethod
    public void createTrip(final ReadableMap map, final Promise promise) {

        if (map.hasKey("tripName") && !map.isNull("tripName") && map.hasKey("deviceId") && !map.isNull("deviceId") && map.hasKey("scheduleEndTime") && !map.isNull("scheduleEndTime") && map.hasKey("metaData") && !map.isNull("metaData") && map.hasKey("tripDestination ") && !map.isNull("tripDestination ") && map.hasKey("tripGeofences ") && !map.isNull("tripGeofences ") && map.hasKey("isForceCloseEnable") && !map.isNull("isForceCloseEnable")) {
            String tripName = map.getString("tripName");
            long deviceId = (long) map.getDouble("deviceId");
            long scheduleEndTime = (long) map.getDouble("scheduleEndTime");
            HashMap<String, String> metaData = createHashMap(map.getMap("metaData"));
            ReadableMap tripDestinationMap = map.getMap("tripDestination");
            TripDestination tripDestination = createTripDestination(tripDestinationMap);
            ReadableArray tripGeofenceList = map.getArray("tripGeofences");
            List<TripGeofence> tripGeofences = createTripGeofenceList(tripGeofenceList);
            boolean isForceCloseEnable = map.getBoolean("isForceCloseEnable");

            InTouch.createTrip(tripName, deviceId, scheduleEndTime, metaData, tripDestination, tripGeofences, isForceCloseEnable, new ICreateTripListener() {
                @Override
                public void onSuccess(String tripId) {
                    promise.resolve(tripId);
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("createTrip Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("tripName") && !map.isNull("tripName") && map.hasKey("deviceId") && !map.isNull("deviceId") && map.hasKey("metaData") && !map.isNull("metaData") && map.hasKey("tripDestination ") && !map.isNull("tripDestination ") && map.hasKey("tripGeofences ") && !map.isNull("tripGeofences ") && map.hasKey("isForceCloseEnable") && !map.isNull("isForceCloseEnable")) {
            // <trip name>, <device id>, <metadata>, <TripDestination class object>, <TripGeoFences class object>,<isFroceCloseEnable>
            String tripName = map.getString("tripName");
            long deviceId = (long) map.getDouble("deviceId");
            HashMap<String, String> metaData = createHashMap(map.getMap("metaData"));
            ReadableMap tripDestinationMap = map.getMap("tripDestination");
            TripDestination tripDestination = createTripDestination(tripDestinationMap);
            ReadableArray tripGeofenceList = map.getArray("tripGeofences");
            List<TripGeofence> tripGeofences = createTripGeofenceList(tripGeofenceList);
            boolean isForceCloseEnable = map.getBoolean("isForceCloseEnable");
            InTouch.createTrip(tripName, deviceId, metaData, tripDestination, tripGeofences, isForceCloseEnable, new ICreateTripListener() {
                @Override
                public void onSuccess(String tripId) {
                    promise.resolve(tripId);
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("createTrip Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("tripName") && !map.isNull("tripName") && map.hasKey("deviceId") && !map.isNull("deviceId") && map.hasKey("metaData") && !map.isNull("metaData") && map.hasKey("isForceCloseEnable") && !map.isNull("isForceCloseEnable")) {
            //<trip name>, <device id>, <metadata>, <isFroceCloseEnable>
            String tripName = map.getString("tripName");
            long deviceId = (long) map.getDouble("deviceId");
            HashMap<String, String> metaData = createHashMap(map.getMap("metaData"));
            boolean isForceCloseEnable = map.getBoolean("isForceCloseEnable");
            InTouch.createTrip(tripName, deviceId, metaData, isForceCloseEnable, new ICreateTripListener() {
                @Override
                public void onSuccess(String tripId) {
                    promise.resolve(tripId);
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("createTrip Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("createTrip Error: ", "Please provide required params");
        }

    }

    @ReactMethod
    public void getTrips(final ReadableMap map, final Promise promise) {

        if (map.hasKey("deviceIds") && !map.isNull("deviceIds") && map.hasKey("limit") && !map.isNull("limit") && map.hasKey("statTimeStamp") && !map.isNull("statTimeStamp") && map.hasKey("endTimeStamp") && !map.isNull("endTimeStamp") && map.hasKey("status") && !map.isNull("status")) {
            Long[] deviceIds = getLongList(map.getArray("deviceIds"));
            int limit = map.getInt("limit");
            int status = map.getInt("status");
            long statTimeStamp = (long) map.getDouble("statTimeStamp");
            long endTimeStamp = (long) map.getDouble("endTimeStamp");

            InTouch.getTrips(deviceIds, limit, status, statTimeStamp, endTimeStamp, new IGetTripsListener() {
                @Override
                public void onSuccess(TripsResponse tripsResponse) {
                    String tripResponseJsonString = new Gson().toJsonTree(tripsResponse, TripsResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(tripResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getTrips Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("limit") && !map.isNull("limit") && map.hasKey("statTimeStamp") && !map.isNull("statTimeStamp") && map.hasKey("endTimeStamp") && !map.isNull("endTimeStamp") && map.hasKey("status") && !map.isNull("status")) {

            int limit = map.getInt("limit");
            int status = map.getInt("status");
            long statTimeStamp = (long) map.getDouble("statTimeStamp");
            long endTimeStamp = (long) map.getDouble("endTimeStamp");

            InTouch.getTrips(limit, status, statTimeStamp, endTimeStamp, new IGetTripsListener() {
                @Override
                public void onSuccess(TripsResponse tripsResponse) {
                    String tripResponseJsonString = new Gson().toJsonTree(tripsResponse, TripsResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(tripResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getTrips Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            InTouch.getTrips(new IGetTripsListener() {
                @Override
                public void onSuccess(TripsResponse tripsResponse) {
                    String tripResponseJsonString = new Gson().toJsonTree(tripsResponse, TripsResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(tripResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getTrips Error: ", s + " " + s1 + " " + s2);
                }
            });

        }
    }

    @ReactMethod
    public void getTripInfo(final ReadableMap map, final Promise promise) {
        if (map.hasKey("tripId") && !map.isNull("tripId") && map.hasKey("isPositionEventsEnable") && !map.isNull("isPositionEventsEnable") && map.hasKey("isLocationEnable") && !map.isNull("isLocationEnable") && map.hasKey("isPolylineEnable") && !map.isNull("isPolylineEnable")) {
            String tripId =  map.getString("tripId");
            boolean isPositionEventsEnable = map.getBoolean("isPositionEventsEnable");
            boolean isLocationEnable = map.getBoolean("isLocationEnable");
            boolean isPolylineEnable = map.getBoolean("isPolylineEnable");
            InTouch.getTripInfo(tripId, isPositionEventsEnable, isLocationEnable, isPolylineEnable, new ITripInfoListener() {
                @Override
                public void onSuccess(TripInfoResponse tripInfoResponse) {
                    String tripInfoJsonString = new Gson().toJsonTree(tripInfoResponse, TripInfoResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(tripInfoJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getTripInfo Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else if (map.hasKey("tripId") && !map.isNull("tripId")) {
            String tripId = map.getString("tripId");
            InTouch.getTripInfo(tripId, new ITripInfoListener() {
                @Override
                public void onSuccess(TripInfoResponse tripInfoResponse) {
                    String tripInfoJsonString = new Gson().toJsonTree(tripInfoResponse, TripInfoResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(tripInfoJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getTripInfo Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("getTripInfo Error: ", "Please provide required params");
        }

    }

    @ReactMethod
    public void closeTrip(final ReadableMap map, final Promise promise) {
        if (map.hasKey("tripId") && !map.isNull("tripId")) {
            String tripId = map.getString("tripId");

            InTouch.closeTrip(tripId, new IResultListener() {
                @Override
                public void onSuccess() {
                    promise.resolve("success");
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("closeTrip Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else {
            promise.reject("closeTrip Error: ", "Please provide required params");
        }

    }

    @ReactMethod
    public void createAlarm(final ReadableMap map, final Promise promise) {
        if (map.hasKey("alarmParameters") && !map.isNull("alarmParameters")) {
            HashMap<String, String> hashMap = createHashMap(map.getMap("alarmParameters"));
            InTouch.createAlarm(hashMap, new ICreateAlarmListener() {
                @Override
                public void onSuccess(CreateAlarmResponse createAlarmResponse) {
                    String createAlarmJsonString = new Gson().toJsonTree(createAlarmResponse, CreateAlarmResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(createAlarmJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("createAlarm Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("closeTrip Error: ", "Please provide required alarm params");
        }


    }

    @ReactMethod
    public void getAlarmConfigs(final ReadableMap map, final Promise promise) {
        if (map.hasKey("alarmIds") && !map.isNull("alarmIds") && map.hasKey("deviceIds") && !map.isNull("deviceIds") && map.hasKey("alarmTypes") && !map.isNull("alarmTypes")) {
            Long[] alarmIds = getLongList(map.getArray("alarmIds"));
            Long[] deviceIds = getLongList(map.getArray("deviceIds"));
            Integer[] alarmTypes = getIntList(map.getArray("alarmTypes"));
            InTouch.getAlarmConfigs(alarmIds, deviceIds, alarmTypes, new IGetAlarmsListener() {
                @Override
                public void onSuccess(InTouchAlarmResponse inTouchAlarmResponse) {
                    String intouchAlarmResponseJsonString = new Gson().toJsonTree(inTouchAlarmResponse, InTouchAlarmResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchAlarmResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getAlarmConfigs Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else {
            InTouch.getAlarmConfigs(new IGetAlarmsListener() {
                @Override
                public void onSuccess(InTouchAlarmResponse inTouchAlarmResponse) {
                    String intouchAlarmResponseJsonString = new Gson().toJsonTree(inTouchAlarmResponse, InTouchAlarmResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchAlarmResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String reason, String errorIdentifier, String errorDescription) {
                    promise.reject("getAlarmConfigs Error: ", reason + " " + errorIdentifier + " " + errorDescription);
                }
            });
        }
    }

    @ReactMethod
    public void updateAlarm(final ReadableMap map, final Promise promise) {
        if (map.hasKey("alarmId") && !map.isNull("alarmId") && map.hasKey("alarmParameters") && !map.isNull("alarmParameters")) {

            long alarmId = (long) map.getDouble("alarmId");
            HashMap<String, String> alarmParameters = createHashMap(map.getMap("alarmParameters"));
//            alarmParameters.entrySet().forEach(entry->{
//                Log.e("TAG",entry.getKey() + " " + entry.getValue());
//            });
            InTouch.updateAlarm(alarmId, alarmParameters, new IUpdateAlarmListener() {
                @Override
                public void onSuccess() {
                    promise.resolve("success");
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("updateAlarm Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else {

            promise.reject("updateAlarm Error: ", "Please provide required params");
        }

    }

    @ReactMethod
    public void deleteAlarm(final ReadableMap map, final Promise promise) {
        if (map.hasKey("alarmIds") && !map.isNull("alarmIds")) {
            Long[] alarmIds = getLongList(map.getArray("alarmIds"));
            InTouch.deleteAlarm(alarmIds, new IResultListener() {
                @Override
                public void onSuccess() {
                    promise.resolve("success");
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("deleteAlarm Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else if (map.hasKey("alarmId") && !map.isNull("alarmId")) {
            long alarmId = (long) (map.getDouble("alarmId"));
            InTouch.deleteAlarm(alarmId, new IResultListener() {
                @Override
                public void onSuccess() {
                    promise.resolve("success");
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("deleteAlarm Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else {
            promise.reject("deleteAlarm Error: ", "Please provide required params");
        }
    }

    @ReactMethod
    public void getAlarmsLogs(final ReadableMap map, final Promise promise) {
        if (map.hasKey("deviceIds") && !map.isNull("deviceIds") && map.hasKey("alarmTypes") && !map.isNull("alarmTypes") && map.hasKey("startTime") && !map.isNull("startTime") && map.hasKey("endTime") && !map.isNull("endTime")) {
            Long[] deviceIds = getLongList(map.getArray("deviceIds"));
            Integer[] alarmTypes = getIntList(map.getArray("alarmTypes"));
            long startTime = (long) map.getDouble("startTime");
            long endTime = (long) map.getDouble("endTime");
            InTouch.getAlarmsLogs(deviceIds, alarmTypes, startTime, endTime, new IGetAlarmsLogsListener() {
                @Override
                public void onSuccess(InTouchAlarmLogsResponse inTouchAlarmLogsResponse) {
                    String intouchAlarmLogsResponseJsonString = new Gson().toJsonTree(inTouchAlarmLogsResponse, InTouchAlarmLogsResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchAlarmLogsResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getAlarmsLogs Error: ", s + " " + s1 + " " + s2);
                }
            });
        } else if (map.hasKey("startTime") && !map.isNull("startTime") && map.hasKey("endTime") && !map.isNull("endTime")) {
            long startTime = (long) map.getDouble("startTime");
            long endTime = (long) map.getDouble("endTime");
            InTouch.getAlarmsLogs(startTime, endTime, new IGetAlarmsLogsListener() {
                @Override
                public void onSuccess(InTouchAlarmLogsResponse inTouchAlarmLogsResponse) {
                    String intouchAlarmLogsResponseJsonString = new Gson().toJsonTree(inTouchAlarmLogsResponse, InTouchAlarmLogsResponse.class).toString();
                    try {
                        promise.resolve(jsonToReact(new JSONObject(intouchAlarmLogsResponseJsonString)));
                    } catch (JSONException e) {
                        promise.reject(e.getMessage(), e.getLocalizedMessage());
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(String s, String s1, String s2) {
                    promise.reject("getAlarmsLogs Error: ", s + " " + s1 + " " + s2);
                }
            });

        } else {
            promise.reject("getAlarmsLogs Error: ", "Please provide required params");
        }


    }


    //helper methods
    private Long[] getLongList(ReadableArray numbers) {
        Long[] result = new Long[numbers.size()];
        for (int i = 0; i < numbers.size(); i++)
            result[i] = (long) numbers.getDouble(i);
        return result;
    }

    private Integer[] getIntList(ReadableArray numbers) {
        Integer[] result = new Integer[numbers.size()];
        for (int i = 0; i < numbers.size(); i++)
            result[i] = numbers.getInt(i);
        return result;
    }

    private List<GeoFencePoint> createGeofencePointList(ReadableArray array) {
        List<GeoFencePoint> list = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            list.add(new GeoFencePoint(array.getArray(i).getDouble(0), array.getArray(i).getDouble(1)));
        }
        return list;
    }

    private HashMap<String, String> createHashMap(final ReadableMap map) {

        HashMap<String, String> hashMap = new HashMap<>();
        ReadableMapKeySetIterator iterator = map.keySetIterator();

        while (iterator.hasNextKey()) {

            String key = iterator.nextKey();
            // hashMap.put(key, map.getString(key));
            ReadableType type = map.getType(key);

            switch (type) {
                case Boolean:
                    hashMap.put(key, String.valueOf(map.getBoolean(key)));
                    break;
                case Number:
                    hashMap.put(key, String.valueOf((long) map.getDouble(key)));
                    break;
                case String:
                    hashMap.put(key, map.getString(key));
                    break;
                case Array:
                    hashMap.put(key,map.getArray(key).toString());
                    break;
            }
        }

        return hashMap;
    }

    private List<TripGeofence> createTripGeofenceList(ReadableArray tripGeofenceList) {
        List<TripGeofence> list = new ArrayList<>();

        for (int i = 0; i < tripGeofenceList.size(); i++) {
            ReadableMap map = tripGeofenceList.getMap(i);
            int radius = map.getInt("radius");
            long scheduledAt = (long) map.getDouble("scheduledAt");
            HashMap<String, String> metaData = createHashMap(map.getMap("metaData"));

//            ReadableMap geometryMap = map.getMap("geometry");
//            String type = geometryMap.getString("type");
//            ReadableArray readableArray = geometryMap.getArray("coordinates");
//            List<Object> coordinates = new ArrayList<>();
//            for (int j = 0; j < readableArray.size(); j++) {
//                ReadableArray array = readableArray.getArray(j);
//                coordinates.add(array);
//            }
//            Geometry geometry = new Geometry(type, coordinates);
            ReadableMap geometryMap = map.getMap("geometry");
            String type = geometryMap.getString("type");
            ReadableArray readableArray = geometryMap.getArray("coordinates");
            List<Double> coordinates = new ArrayList<>();
            for (int j = 0; j < readableArray.size(); j++) {
                coordinates.add(readableArray.getDouble(i));
            }
            Geometry geometry = new Geometry(type, coordinates);

            list.add(new TripGeofence(geometry, radius, scheduledAt, metaData));
        }

        return list;
    }

    private TripDestination createTripDestination(ReadableMap map) {
        TripDestination tripDestination = new TripDestination();
        if (map.hasKey("metaData") && !map.isNull("metaData")) {
            tripDestination.setMetadata(createHashMap(map.getMap("metaData")));
        }
        if (map.hasKey("scheduledAt") && !map.isNull("scheduledAt")) {
            tripDestination.setScheduledAt((long) map.getDouble("scheduledAt"));
        }
        if (map.hasKey("radius") && !map.isNull("radius")) {
            tripDestination.setRadius(map.getInt("radius"));
        }

        if (map.hasKey("geometry") && !map.isNull("geometry")) {
            ReadableMap geometryMap = map.getMap("geometry");
            String type = geometryMap.getString("type");
            ReadableArray readableArray = geometryMap.getArray("coordinates");
            List<Double> coordinates = new ArrayList<>();
            for (int i = 0; i < readableArray.size(); i++) {
                coordinates.add(readableArray.getDouble(i));
            }
            // coordinates.add(77.0);
            // coordinates.add(28.0);
            Geometry geometry = new Geometry(type, coordinates);
            tripDestination.setGeometry(geometry);
        }
        return tripDestination;
    }
}
