package com.indigitall.cordova;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

import com.indigitall.android.commons.utils.CorePreferenceUtils;
import com.indigitall.android.commons.Constants;
import com.indigitall.android.commons.models.CorePushAction;
import com.indigitall.android.commons.models.ErrorModel;

import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
import android.content.pm.PackageManager;

import com.indigitall.android.commons.models.LogLevel;
import com.indigitall.android.push.callbacks.EventCallback;
import com.indigitall.android.push.callbacks.PushTokenCallback;

import com.indigitall.android.Indigitall;
import com.indigitall.android.push.Configuration;
import com.indigitall.android.push.callbacks.DeviceCallback;

import com.indigitall.android.push.callbacks.TopicsCallback;
import com.indigitall.android.push.models.CustomNotificationChannel;
import com.indigitall.android.push.models.Device;
import com.indigitall.android.push.models.ExternalApp;
import com.indigitall.android.push.models.PermissionStatus;
import com.indigitall.android.push.models.Push;
import com.indigitall.android.push.models.PushButton;
import com.indigitall.android.push.models.PushErrorModel;
import com.indigitall.android.push.models.Topic;

import android.webkit.WebView;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;

import com.indigitall.android.push.models.Permission;
import com.indigitall.android.push.callbacks.InitCallBack;
import com.indigitall.android.push.utils.FirebaseUtils;
import com.indigitall.android.push.utils.PushServiceUtils;
import com.indigitall.android.push.utils.ServiceUtils;
import com.indigitall.cordova.inapp.CordovaIndigitallInApp;
import com.indigitall.cordova.interfaces.IndigitallFirebaseInterface;
import com.indigitall.cordova.utils.CordovaPreferenceUtils;
import com.indigitall.cordova.utils.PushParseUtils;

import java.util.ArrayList;

public class CordovaIndigitall extends CordovaPlugin implements IndigitallFirebaseInterface {
    private static final String TAG = "CordovaIndigitall";
    private static final String ACTION_INIT = "initialize";
    private static final String ACTION_DEVICE_GET = "deviceGet";
    private static final String ACTION_DEVICE_ENABLE = "deviceEnable";
    private static final String ACTION_DEVICE_DISABLE = "deviceDisable";
    private static final String ACTION_TOPICS_LIST = "topicsList";
    private static final String ACTION_TOPICS_SUBSCRIBE = "topicsSubscribe";
    private static final String ACTION_TOPICS_UNSUBSCRIBE = "topicsUnsubscribe";
    private static final String ACTION_EXTERNALCODE = "setExternalCode";
    private static final String ACTION_SHOWINAPP = "showInApp";
    private static final String ACTION_SHOWMULTIPLEINAPP = "showMultipleInApp";
    private static final String ACTION_SHOWPOPUP = "showPopUp";
    private static final String ACTION_SENDCUSTOMEVENT = "sendCustomEvent";
    private static final String ACTION_GET_PACKAGE_NAME = "packageName";
    private static final int REQUEST_CODE_ASK_PERMISSIONS = 50001;
    private static final String ACTION_GET_PUSH = "getPush";
    private static final String ACTION_LOGIN = "logIn";
    private static final String ACTION_LOGOUT = "logOut";
    private static final String ACTION_INAPP_IS_WAS_SHOWN = "inAppWasShown";
    private static final String ACTION_INAPP_TIMES_CLICKED = "inAppTimesClicked";
    private static final String ACTION_INAPP_ADD_NEW_CLICK = "inAppAddNewClick";
    private static final String ACTION_ADD_NEW_INAPP_TO_DISMISS_FOREVER = "addNewInAppToDismissForever";

    private static final String ACTION_EVENT_CLICK_INAPP_REQUEST = "eventClickInAppRequest";
    private static final String ACTION_EVENT_PRINT_INAPP_REQUEST = "eventPrintInAppRequest";
    private static final String ACTION_ON_MESSAGE_RECEIVED = "onMessageReceived";
    private static final String ACTION_GET_TOKEN = "getToken";
    private static final String ACTION_IS_INDIGITALL_PUSH_NOTIFICATION = "isIndigitallPushNotification";
    private static final String ACTION_ON_INDIGITALL_GET_PUSH = "onIndigitallGetPush";
    private static final String ACTION_ON_SET_DEFAULT_VIEW_URL = "setDefaultViewUrl";
    private static final String ACTION_ON_CLEAR_VIEW_URL = "clearViewUrl";
    private static final String ACTION_IS_PUSH_SECURE = "isPushSecure";

    private static final String ACTION_REQUEST_PUSH_PERMISSION = "requestPushPermissions";

    private static final String ACTION_GET_PUSH_PERMISSION_STATUS = "getPushPermissionStatus";

    private static CallbackContext notificationCallback;
    public static CallbackContext getPushCallback;
    public static IndigitallFirebaseInterface indigitallInterface;

    @Override
    public boolean execute(String action, JSONArray params, CallbackContext callback) throws JSONException {
        Log.d(TAG, "Action: " + action);
        Context context = cordova.getActivity().getApplicationContext();
        if (ACTION_INIT.equals(action)) {
            return init(context, params, callback);
        } else if (ACTION_GET_PACKAGE_NAME.equals(action)) {
            return getPackageName(context, callback);
        } else if (ACTION_DEVICE_GET.equals(action)) {
            return deviceGet(context, callback);
        } else if (ACTION_DEVICE_ENABLE.equals(action)) {
            return deviceEnable(context, callback);
        } else if (ACTION_DEVICE_DISABLE.equals(action)) {
            return deviceDisable(context, callback);
        } else if (ACTION_TOPICS_LIST.equals(action)) {
            return topicsList(context, callback);
        } else if (ACTION_TOPICS_SUBSCRIBE.equals(action)) {
            return topicsSubscribe(context, params, callback);
        } else if (ACTION_TOPICS_UNSUBSCRIBE.equals(action)) {
            return topicsUnsubscribe(context, params, callback);
        } else if (ACTION_EXTERNALCODE.equals(action)) {
            return setExternalCode(context, params, callback);
        } else if (ACTION_SENDCUSTOMEVENT.equals(action)) {
            return sendCustomEvent(context, params, callback);
        } else if (ACTION_GET_PUSH.equals(action)) {
            return getPush(context, callback);
        } else if (ACTION_ON_INDIGITALL_GET_PUSH.equals(action)) {
            return onIndigitallGetPush(context, null, callback);
        } else if (ACTION_ON_SET_DEFAULT_VIEW_URL.equals(action)) {
            return setDefaultViewUrl(context, params);
        } else if (ACTION_ON_CLEAR_VIEW_URL.equals(action)) {
            return clearViewUrl(context);
        } else if (ACTION_ON_MESSAGE_RECEIVED.equals(action)) {
            return onIndigitallMessageReceived(context, null, callback);
        } else if (ACTION_GET_TOKEN.equals(action)) {
            return getToken(context, callback);
        } else if (ACTION_IS_INDIGITALL_PUSH_NOTIFICATION.equals(action)) {
            return isIndigitallPushNotification(context, params, callback);
        } else if (ACTION_LOGIN.equals(action)) {
            return logIn(context, params, callback);
        } else if (ACTION_LOGOUT.equals(action)) {
            return logOut(context, callback);
        } else if (ACTION_REQUEST_PUSH_PERMISSION.equals(action)) {
            return requestPushPermission(context);
        } else if (ACTION_GET_PUSH_PERMISSION_STATUS.equals(action)) {
            return getPushPermissionStatus(context, callback);
        } else if (ACTION_SHOWPOPUP.equals(action)) {
            return showPopUp(params, callback);
        } else if (ACTION_INAPP_IS_WAS_SHOWN.equals(action)) {
            return inAppIsWasShown(context, params, callback);
        } else if (ACTION_INAPP_ADD_NEW_CLICK.equals(action)) {
            return inAppAddNewClick(context, params, callback);
        } else if (ACTION_ADD_NEW_INAPP_TO_DISMISS_FOREVER.equals(action)) {
            return addNewInAppToDismissForever(context, params, callback);
        } else if (ACTION_EVENT_PRINT_INAPP_REQUEST.equals(action)) {
            return eventPrintInAppRequest(context, params, callback);
        } else if (ACTION_EVENT_CLICK_INAPP_REQUEST.equals(action)) {
            return eventClickInAppRequest(context, params, callback);
        } else if (ACTION_IS_PUSH_SECURE.equals(action)) {
            return isPushSecure(context, params, callback);
        }
        return false;
    }

    private boolean requestPushPermission(Context context) {
        if (Build.VERSION.SDK_INT >= 33) {
            String permission = "android.permission.POST_NOTIFICATIONS";
            int code = Constants.REQUEST_PERMISSION_CODE;
            ArrayList<String> permissions = new ArrayList<>();
            permissions.add(permission);
            CordovaPlugin plugin = this;
            cordova.getThreadPool().execute(new Runnable() {
                @Override
                public void run() {
                    cordova.requestPermission(plugin, code, permission);
                }
            });

        }
        return true;
    }

    private boolean getPushPermissionStatus(Context context, final CallbackContext callback) {
        String permission = "android.permission.POST_NOTIFICATIONS";
        try {
            cordova.getThreadPool().execute(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
                        if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {
                            callback.success("granted");
                        } else {
                            callback.success("denied");
                        }
                    } else {
                        if (ContextCompat.checkSelfPermission(context,
                                permission) != PackageManager.PERMISSION_GRANTED) {
                            callback.success("denied");
                        } else {
                            callback.success("granted");
                        }
                    }
                }
            });
        } catch (Exception ex) {
            callback.error(ex.getMessage());
        }
        return true;
    }

    private boolean init(Context context, JSONArray params, final CallbackContext callback) {
        final String JSON_APP_KEY = "appKey";
        final String JSON_SENDER_ID = "senderId";
        final String JSON_REQUEST_LOCATION = "requestLocation";
        final String JSON_PRODUCT_NAME = "productName";
        final String JSON_PRODUCT_VERSION = "productVersion";
        final String JSON_WIFI_FILTER = "wifiFilterEnabled";
        final String JSON_URL_DEVICE_API = "urlDeviceApi";
        final String JSON_URL_INBOX_API = "urlInboxApi";
        final String JSON_SET_ALWAYS_LAUNCH_ON_INIT = "alwaysLaunchOnInit";
        final String JSON_SET_AUTO_REQUEST_PUSH_PERMISSION = "autoRequestPushPermission";
        final String JSON_AVOID_CYPHER = "avoidCypher";
        final String JSON_DISABLED_PUSH_SERVICE = "disabledPushService";
        final String JSON_BACKGROUND_REQUESTS_DISABLED = "backgroundRequestsDisabled";
        final String JSON_TIMEOUT_REQUESTS_IN_MILLISECONDS = "timeoutRequestsInMilliseconds";
        final String JSON_LOG_LEVEL = "logLevel";
        final String JSON_NOTIFICATION_CHANNEL = "customNotificationChannel";
        final String JSON_NOTIFICATION_CHANNEL_ID = "channelID";
        final String JSON_NOTIFICATION_CHANNEL_NAME = "channelName";

        String appKey = null,
                senderId = null,
                productName = null,
                productVersion = null,
                urlDeviceApi = "https://device-api.indigitall.com/v1",
                urlInboxApi = "https://inbox-api.indigitall.com/v1";
        boolean requestLocation = false,
                alwaysLaunchOnInit = false,
                autoRequestPushPermission = true,
                avoidCypher = false,
                disabledPushService = false,
                wifiFilterEnabled = false,
                backgroundRequestsDisabled = false;
        int timeoutRequestsInMilliseconds = 0;
        LogLevel logLevel = null;
        CustomNotificationChannel customNotificationChannel = null;

        try {
            if (params.length() > 0 && params.get(0) instanceof JSONObject) {
                JSONObject obj = params.getJSONObject(0);
                if (obj.has(JSON_APP_KEY))
                    appKey = obj.getString(JSON_APP_KEY);
                if (obj.has(JSON_SENDER_ID))
                    senderId = obj.getString(JSON_SENDER_ID);
                if (obj.has(JSON_REQUEST_LOCATION))
                    requestLocation = obj.getBoolean(JSON_REQUEST_LOCATION);
                if (obj.has(JSON_PRODUCT_NAME))
                    productName = obj.getString(JSON_PRODUCT_NAME);
                if (obj.has(JSON_PRODUCT_VERSION))
                    productVersion = obj.getString(JSON_PRODUCT_VERSION);
                if (obj.has(JSON_WIFI_FILTER))
                    wifiFilterEnabled = obj.getBoolean(JSON_WIFI_FILTER);
                if (obj.has(JSON_URL_DEVICE_API))
                    urlDeviceApi = obj.getString(JSON_URL_DEVICE_API);
                if (obj.has(JSON_URL_INBOX_API))
                    urlInboxApi = obj.getString(JSON_URL_INBOX_API);
                if (obj.has(JSON_SET_ALWAYS_LAUNCH_ON_INIT))
                    alwaysLaunchOnInit = obj.getBoolean(JSON_SET_ALWAYS_LAUNCH_ON_INIT);
                if (obj.has(JSON_AVOID_CYPHER))
                    avoidCypher = obj.getBoolean(JSON_AVOID_CYPHER);
                if (obj.has(JSON_DISABLED_PUSH_SERVICE))
                    disabledPushService = obj.getBoolean(JSON_DISABLED_PUSH_SERVICE);
                if (obj.has(JSON_SET_AUTO_REQUEST_PUSH_PERMISSION))
                    autoRequestPushPermission = obj.getBoolean(JSON_SET_AUTO_REQUEST_PUSH_PERMISSION);
                if (obj.has(JSON_BACKGROUND_REQUESTS_DISABLED))
                    backgroundRequestsDisabled = obj.getBoolean(JSON_BACKGROUND_REQUESTS_DISABLED);
                if (obj.has(JSON_TIMEOUT_REQUESTS_IN_MILLISECONDS))
                    timeoutRequestsInMilliseconds = obj.getInt(JSON_TIMEOUT_REQUESTS_IN_MILLISECONDS);

                if (obj.has(JSON_LOG_LEVEL)) {
                    int logLevelNumber = obj.getInt(JSON_LOG_LEVEL);
                    switch (logLevelNumber) {
                        case 1:
                            logLevel = LogLevel.DEBUG;
                            break;
                        case 2:
                            logLevel = LogLevel.INFO;
                            break;
                        case 3:
                            logLevel = LogLevel.WARNING;
                            break;
                        case 4:
                            logLevel = LogLevel.ERROR;
                            break;
                        default:
                            logLevel = LogLevel.DEBUG;
                            break;
                    }
                }

                if (obj.has(JSON_NOTIFICATION_CHANNEL)) {
                    JSONObject channel = obj.getJSONObject(JSON_NOTIFICATION_CHANNEL);
                    String channelID = channel.getString(JSON_NOTIFICATION_CHANNEL_ID);
                    String channelName = channel.getString(JSON_NOTIFICATION_CHANNEL_NAME);

                    if (!channelID.isEmpty() && !channelName.isEmpty()) {
                        customNotificationChannel = new CustomNotificationChannel(channelID, channelName);
                    }
                }
            }
        } catch (JSONException ex) {
            ex.printStackTrace();
        }
        ArrayList<String> permissions = new ArrayList<>();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // push check permission override location permission on sdk > 33
            if (autoRequestPushPermission && Build.VERSION.SDK_INT >= 33) {
                if (cordova.getActivity().checkSelfPermission(
                        "android.permission.POST_NOTIFICATIONS") != PackageManager.PERMISSION_GRANTED) {
                    permissions.add("android.permission.POST_NOTIFICATIONS");
                }
            }
            if (requestLocation && cordova.getActivity().checkSelfPermission(
                    Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
            }
            if (permissions.size() > 0)
                cordova.requestPermissions(this, 50, permissions.toArray(new String[permissions.size()]));
        }

        if (appKey != null && senderId != null) {
            Configuration config = new Configuration.Builder(appKey, senderId)
                    .setDefaultActivity(cordova.getActivity().getClass().getName())
                    .setAutoRequestPermissionLocation(requestLocation)
                    // .setProductName(productName)
                    // .setProductVersion(productVersion)
                    .wifiFilterEnabled(wifiFilterEnabled)
                    .setUrlDeviceApi(urlDeviceApi)
                    .setUrlInboxApi(urlInboxApi)
                    .setAlwaysLaunchOnInit(alwaysLaunchOnInit)
                    .setAvoidCypher(avoidCypher)
                    .setPushServiceDisabled(disabledPushService)
                    .setAutoRequestPushPermission(autoRequestPushPermission)
                    .setTimeoutRequestsInMilliseconds(timeoutRequestsInMilliseconds)
                    .setBackgroundRequestsDisabled(backgroundRequestsDisabled)
                    .setLogDebug(logLevel)
                    .setCustomNotificationChannel(customNotificationChannel)
                    .build();
            CorePreferenceUtils.setProductName(context, productName);
            CorePreferenceUtils.setProductVersion(context, productVersion);
            // llamada init
            Indigitall.init(context, config, new InitCallBack(context) {

                @Override
                public void onIndigitallInitialized(Permission[] permissions, Device device) {
                    callback.success(PushParseUtils.jsonFromDevice(device));
                }

                @Override
                public void onNewUserRegistered(Device device) {
                    callback.success(PushParseUtils.jsonFromDevice(device));
                }

                @Override
                public void onErrorInitialized(ErrorModel errorModel) {
                    callback.error(errorModel.getErrorMessage().getErrorMessage());
                }
            });
        }

        return true;
    }

    private boolean getPackageName(Context context, final CallbackContext callback) {
        if (context.getPackageName() != null) {
            callback.success(context.getPackageName());
        } else {
            callback.error(context.getPackageName());
        }
        return true;
    }

    private boolean deviceGet(Context context, final CallbackContext callback) {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Indigitall.deviceGet(context, new DeviceCallback(context) {
                    @Override
                    public void onSuccess(Device device) {
                        callback.success(PushParseUtils.jsonFromDevice(device));
                    }

                    @Override
                    public void onFail(ErrorModel errorModel) {
                        callback.error(errorModel.getErrorMessage().getErrorMessage());
                    }

                });
            }
        });

        return true;
    }

    private boolean deviceEnable(Context context, final CallbackContext callback) {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Indigitall.deviceEnable(context, new DeviceCallback(context) {
                    @Override
                    public void onSuccess(Device device) {
                        callback.success(PushParseUtils.jsonFromDevice(device));
                    }

                    @Override
                    public void onFail(ErrorModel errorModel) {
                        callback.error(errorModel.getErrorMessage().getErrorMessage());
                    }
                });
            }
        });
        return true;
    }

    private boolean deviceDisable(Context context, final CallbackContext callback) {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Indigitall.deviceDisable(context, new DeviceCallback(context) {
                    @Override
                    public void onSuccess(Device device) {
                        callback.success(PushParseUtils.jsonFromDevice(device));
                    }

                    @Override
                    public void onFail(ErrorModel errorModel) {
                        callback.error(errorModel.getErrorMessage().getErrorMessage());
                    }
                });
            }
        });

        return true;
    }

    private boolean topicsList(Context context, final CallbackContext callback) {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Indigitall.topicsList(context, new TopicsCallback() {
                    @Override
                    public void onSuccess(Topic[] topics) {
                        callback.success(PushParseUtils.jsonArrayFromTopicArray(topics));
                    }

                    @Override
                    public void onFail(ErrorModel errorModel) {
                        callback.error(errorModel.getErrorMessage().getErrorMessage());
                    }
                });
            }
        });
        return true;
    }

    private boolean topicsSubscribe(Context context, JSONArray params, final CallbackContext callback) {
        String[] topics = PushParseUtils.parseTopicArray(params);
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Indigitall.topicsSubscribe(context, topics, new TopicsCallback() {
                    @Override
                    public void onSuccess(Topic[] topics) {
                        callback.success(PushParseUtils.jsonArrayFromTopicArray(topics));
                    }

                    @Override
                    public void onFail(ErrorModel errorModel) {
                        callback.error(errorModel.getErrorMessage().getErrorMessage());
                    }
                });
            }
        });
        return true;
    }

    private boolean topicsUnsubscribe(Context context, JSONArray params, final CallbackContext callback) {
        String[] topics = PushParseUtils.parseTopicArray(params);
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Indigitall.topicsUnsubscribe(context, topics, new TopicsCallback() {
                    @Override
                    public void onSuccess(Topic[] topics) {
                        callback.success(PushParseUtils.jsonArrayFromTopicArray(topics));
                    }

                    @Override
                    public void onFail(ErrorModel errorModel) {
                        callback.error(errorModel.getErrorMessage().getErrorMessage());
                    }
                });
            }
        });

        return true;
    }

    private boolean setExternalCode(Context context, JSONArray params, final CallbackContext callback) {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Indigitall.setExternalCode(context, params.getJSONObject(0).getString("externalCode"),
                            new DeviceCallback(context) {
                                @Override
                                public void onSuccess(Device device) {
                                    callback.success(PushParseUtils.jsonFromDevice(device));
                                }

                                @Override
                                public void onFail(ErrorModel errorModel) {
                                    callback.error(errorModel.getErrorMessage().getErrorMessage());
                                }
                            });
                } catch (JSONException e) {
                    callback.error(e.getMessage());
                }
            }
        });
        return true;
    }

    private boolean getPush(Context context, final CallbackContext callback) throws JSONException {
        if (cordova.getActivity().getIntent() != null && cordova.getActivity().getIntent().getExtras() != null) {
            Bundle extras = cordova.getActivity().getIntent().getExtras();
            if (extras != null && extras.containsKey(Push.EXTRA_PUSH)) {
                Push push = null;
                if (context != null) {
                    push = new Push(context, extras.getString(Push.EXTRA_PUSH));
                } else {
                    push = new Push(extras.getString(Push.EXTRA_PUSH));
                }
                String url = CordovaPreferenceUtils.getPushUrl(context);
                if (url != null && !url.equals("")) {
                    webViewLoadUrl("file:///android_asset/www/" + url);
                } else {
                    webViewLoadUrl(webView.getUrl());
                }
                callback.success(PushParseUtils.jsonFromPush(push));
            } else {
                callback.error("No extras on intent");
            }
        } else {
            callback.error("No push was getting");
        }
        return true;
    }

    private void webViewLoadUrl(String url) {
        cordova.getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (webView != null) {
                    webView.loadUrl(url);
                    cordova.getActivity().setIntent(null);
                }
            }
        });
    }

    @Override
    public boolean onIndigitallGetPush(Context context, JSONObject json, CallbackContext callback) {
        if (json != null) {
            if (getPushCallback != null) {
                cordova.getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (webView != null) {
                            String url = CordovaPreferenceUtils.getPushUrl(context);
                            String urlNative = CordovaPreferenceUtils.getNativePushUrl(context);
                            if (urlNative != null && !urlNative.equals("") && !urlNative.equals(webView.getUrl())) {
                                webView.loadUrl(urlNative);
                            } else if (url != null && !url.equals("")) {
                                String completeUrl = "file:///android_asset/www/" + url;
                                if (!completeUrl.equals(webView.getUrl())) {
                                    webView.loadUrl(completeUrl);
                                }
                            }
                        }
                    }
                });
                Push push = new Push(context, json);
                PluginResult pluginresult = new PluginResult(PluginResult.Status.OK, PushParseUtils.jsonFromPush(push));
                pluginresult.setKeepCallback(true);
                getPushCallback.sendPluginResult(pluginresult);
            }
        } else {
            getPushCallback = callback;
            indigitallInterface = this;
            cordova.getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    String url = webView.getUrl();
                    String urlGetPushMethod = CordovaPreferenceUtils.getPushUrl(context);
                    if (urlGetPushMethod == null || urlGetPushMethod.equals("")) {
                        CordovaPreferenceUtils.setNativePushUrl(context, url);
                    }
                    PluginResult pluginresult = new PluginResult(PluginResult.Status.NO_RESULT, new JSONObject());
                    if (CordovaPreferenceUtils.getPushString(context) != null &&
                            !CordovaPreferenceUtils.getPushString(context).equals("")) {
                        Push push = new Push(context, CordovaPreferenceUtils.getPushString(context));
                        pluginresult = new PluginResult(PluginResult.Status.OK, PushParseUtils.jsonFromPush(push));
                        CordovaPreferenceUtils.setPushString(context, "");
                    }
                    pluginresult.setKeepCallback(true);
                    getPushCallback.sendPluginResult(pluginresult);
                }
            });
        }
        return true;
    }

    public boolean setDefaultViewUrl(Context context, JSONArray params) {
        try {
            String defaultViewUrl = params.get(0).toString();
            CordovaPreferenceUtils.setPushUrl(context, defaultViewUrl);
            CordovaPreferenceUtils.setNativePushUrl(context, "");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return true;
    }

    public boolean clearViewUrl(Context context) {
        CordovaPreferenceUtils.setPushUrl(context, "");
        CordovaPreferenceUtils.setNativePushUrl(context, "");
        return true;
    }

    @Override
    public boolean onIndigitallMessageReceived(Context context, JSONObject json, CallbackContext callback) {

        if (json != null) {
            if (notificationCallback != null) {
                PluginResult pluginresult = new PluginResult(PluginResult.Status.OK, json);
                pluginresult.setKeepCallback(true);
                notificationCallback.sendPluginResult(pluginresult);
            } else {
                cordova.getThreadPool().execute(new Runnable() {
                    @Override
                    public void run() {
                        FirebaseUtils.showNotification(context, json);
                    }
                });
            }
        } else {
            notificationCallback = callback;
            indigitallInterface = this;
            PluginResult pluginresult = new PluginResult(PluginResult.Status.NO_RESULT, new JSONObject());
            pluginresult.setKeepCallback(true);
            notificationCallback.sendPluginResult(pluginresult);
        }
        return true;
    }

    private boolean isIndigitallPushNotification(Context context, JSONArray params, CallbackContext callback) {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                boolean isIndigitallPush = false;
                try {
                    if (params.length() > 0 && params.get(0) instanceof JSONObject) {
                        JSONObject json = params.getJSONObject(0);
                        if (json != null) {
                            Push push = new Push(context, json);
                            if (push != null &&
                                    push.getAppKey() != null) {
                                isIndigitallPush = true;
                            }
                        }
                    }
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
                if (isIndigitallPush) {
                    callback.success();
                } else {
                    callback.error("Not an Indigitall push");
                }
            }
        });
        return true;
    }

    private boolean isPushSecure(Context context, JSONArray params, CallbackContext callback) throws JSONException {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                boolean isPushSecure = false;
                try {
                    if (params.length() > 0 && params.get(0) instanceof JSONObject) {
                        JSONObject json = null;
                        json = params.getJSONObject(0);
                        if (json != null) {
                            Push push = new Push(context, json);
                            if (push != null &&
                                    push.getAppKey() != null &&
                                    PushServiceUtils.isPushSecure(context, push)) {
                                isPushSecure = true;
                            }
                        }
                    }
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
                if (isPushSecure) {
                    callback.success();
                } else {
                    callback.error("Not an Indigitall push secure");
                }
            }
        });
        return true;
    }

    private boolean getToken(Context context, final CallbackContext callback) throws JSONException {
        ServiceUtils.getPushToken(context, new PushTokenCallback() {
            @Override
            public void onSuccess(@Nullable String s) {
                callback.success(s);
            }

            @Override
            public void onError(PushErrorModel pushErrorModel) {
                callback.error(pushErrorModel.getErrorMessage().getErrorMessage());
            }

        });
        return true;
    }

    private boolean sendCustomEvent(Context context, JSONArray params, final CallbackContext callback)
            throws JSONException {
        String JSON_EVENT = "event";
        String JSON_EVENT_DATA = "customData";
        String JSON_EVENT_ID = "eventId";
        String JSON_EVENT_AT = "eventAt";
        String eventCustom = null;
        String eventId = null;
        String eventAt = null;
        JSONObject eventCustomData = null;
        if (params.length() > 0 && params.get(0) instanceof JSONObject) {
            JSONObject obj = params.getJSONObject(0);
            if (obj.has(JSON_EVENT))
                eventCustom = obj.getString(JSON_EVENT);
            if (obj.has(JSON_EVENT_DATA))
                eventCustomData = new JSONObject(obj.getString(JSON_EVENT_DATA));
            if (obj.has(JSON_EVENT_ID))
                eventId = obj.getString(JSON_EVENT_ID);
            if (obj.has(JSON_EVENT_AT))
                eventAt = obj.getString(JSON_EVENT_AT);
        }
        Indigitall.sendCustomEvent(context, eventCustom, eventId, eventAt, eventCustomData, new EventCallback(context) {
            @Override
            public void onError(ErrorModel errorModel) {
                callback.error(errorModel.getErrorMessage().getErrorMessage());
            }

            @Override
            public void onSuccess() {
                callback.success();
            }

        });
        return true;
    }

    private boolean logIn(Context context, JSONArray params, final CallbackContext callback) throws JSONException {
        Indigitall.logIn(context, params.get(0).toString(), new DeviceCallback(context) {
            @Override
            public void onSuccess(Device device) {
                callback.success(PushParseUtils.jsonFromDevice(device));
            }

            @Override
            public void onFail(ErrorModel errorModel) {
                callback.error(errorModel.getErrorMessage().getErrorMessage());
            }
        });
        return true;
    }

    private boolean logOut(Context context, final CallbackContext callback) throws JSONException {
        Indigitall.logOut(context, new DeviceCallback(context) {
            @Override
            public void onSuccess(Device device) {
                callback.success(PushParseUtils.jsonFromDevice(device));
            }

            @Override
            public void onFail(ErrorModel errorModel) {
                callback.error(errorModel.getErrorMessage().getErrorMessage());
            }
        });
        return true;
    }

    private boolean showPopUp(JSONArray params, final CallbackContext callback) throws JSONException {
        return new CordovaIndigitallInApp().execute(ACTION_SHOWPOPUP, params, callback);
    }

    private boolean inAppIsWasShown(Context context, JSONArray params, final CallbackContext callback)
            throws JSONException {
        return new CordovaIndigitallInApp().execute(ACTION_INAPP_IS_WAS_SHOWN, params, callback);
    }

    private boolean inAppAddNewClick(Context context, JSONArray params, final CallbackContext callback)
            throws JSONException {
        return new CordovaIndigitallInApp().execute(ACTION_INAPP_ADD_NEW_CLICK, params, callback);
    }

    private boolean eventPrintInAppRequest(Context context, JSONArray params, final CallbackContext callback)
            throws JSONException {
        return new CordovaIndigitallInApp().execute(ACTION_EVENT_PRINT_INAPP_REQUEST, params, callback);
    }

    private boolean eventClickInAppRequest(Context context, JSONArray params, final CallbackContext callback)
            throws JSONException {
        return new CordovaIndigitallInApp().execute(ACTION_EVENT_CLICK_INAPP_REQUEST, params, callback);
    }

    private boolean addNewInAppToDismissForever(Context context, JSONArray params, final CallbackContext callback)
            throws JSONException {
        return new CordovaIndigitallInApp().execute(ACTION_ADD_NEW_INAPP_TO_DISMISS_FOREVER, params, callback);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
            throws JSONException {
        Indigitall.onRequestPermissionsResult(cordova.getContext().getApplicationContext(), requestCode, permissions,
                grantResults);
    }
}
