/**
 * Modified MIT License
 *
 * Copyright 2021 OneSignal
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * 1. The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * 2. All copies of substantial portions of the Software may only be used in connection
 * with services provided by OneSignal.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.onesignal.cordova;

import com.onesignal.OneSignal;
import com.onesignal.common.OneSignalWrapper;
import com.onesignal.debug.internal.logging.Logging;
import com.onesignal.inAppMessages.IInAppMessage;
import com.onesignal.inAppMessages.IInAppMessageClickEvent;
import com.onesignal.inAppMessages.IInAppMessageClickListener;
import com.onesignal.inAppMessages.IInAppMessageClickResult;
import com.onesignal.inAppMessages.IInAppMessageDidDismissEvent;
import com.onesignal.inAppMessages.IInAppMessageDidDisplayEvent;
import com.onesignal.inAppMessages.IInAppMessageLifecycleListener;
import com.onesignal.inAppMessages.IInAppMessageWillDismissEvent;
import com.onesignal.inAppMessages.IInAppMessageWillDisplayEvent;
import com.onesignal.notifications.INotification;
import com.onesignal.notifications.INotificationClickEvent;
import com.onesignal.notifications.INotificationClickListener;
import com.onesignal.notifications.INotificationClickResult;
import com.onesignal.notifications.INotificationLifecycleListener;
import com.onesignal.notifications.INotificationWillDisplayEvent;
import java.util.HashMap;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class OneSignalPush extends CordovaPlugin
        implements INotificationLifecycleListener,
                INotificationClickListener,
                IInAppMessageLifecycleListener,
                IInAppMessageClickListener {
    private static final String TAG = "OneSignalPush";

    private static final String ADD_FOREGROUND_LIFECYCLE_LISTENER = "addForegroundLifecycleListener";
    private static final String PROCEED_WITH_WILL_DISPLAY = "proceedWithWillDisplay";
    private static final String DISPLAY_NOTIFICATION = "displayNotification";
    private static final String PREVENT_DEFAULT = "preventDefault";
    private static final String ADD_NOTIFICATION_CLICK_LISTENER = "addNotificationClickListener";

    private static final String SET_IN_APP_MESSAGE_CLICK_HANDLER = "setInAppMessageClickHandler";
    private static final String SET_ON_WILL_DISPLAY_IN_APP_MESSAGE_HANDLER = "setOnWillDisplayInAppMessageHandler";
    private static final String SET_ON_DID_DISPLAY_IN_APP_MESSAGE_HANDLER = "setOnDidDisplayInAppMessageHandler";
    private static final String SET_ON_WILL_DISMISS_IN_APP_MESSAGE_HANDLER = "setOnWillDismissInAppMessageHandler";
    private static final String SET_ON_DID_DISMISS_IN_APP_MESSAGE_HANDLER = "setOnDidDismissInAppMessageHandler";

    private static final String INIT = "init";

    private static final String SET_LANGUAGE = "setLanguage";

    private static final String LOGIN = "login";
    private static final String LOGOUT = "logout";

    private static final String ADD_PERMISSION_OBSERVER = "addPermissionObserver";
    private static final String ADD_PUSH_SUBSCRIPTION_OBSERVER = "addPushSubscriptionObserver";
    private static final String ADD_USER_STATE_OBSERVER = "addUserStateObserver";

    private static final String GET_ONESIGNAL_ID = "getOnesignalId";
    private static final String GET_EXTERNAL_ID = "getExternalId";

    private static final String OPT_IN = "optInPushSubscription";
    private static final String OPT_OUT = "optOutPushSubscription";
    private static final String GET_ID = "getPushSubscriptionId";
    private static final String GET_TOKEN = "getPushSubscriptionToken";
    private static final String GET_OPTED_IN = "getPushSubscriptionOptedIn";

    private static final String ADD_ALIASES = "addAliases";
    private static final String REMOVE_ALIASES = "removeAliases";

    private static final String REMOVE_TAGS = "removeTags";
    private static final String ADD_TAGS = "addTags";
    private static final String GET_TAGS = "getTags";

    private static final String REGISTER_FOR_PROVISIONAL_AUTHORIZATION = "registerForProvisionalAuthorization";
    private static final String REQUEST_PERMISSION = "requestPermission";
    private static final String GET_PERMISSION_INTERNAL = "getPermissionInternal";
    private static final String PERMISSION_NATIVE = "permissionNative";
    private static final String CAN_REQUEST_PERMISSION = "canRequestPermission";

    private static final String CLEAR_ALL_NOTIFICATIONS = "clearAllNotifications";
    private static final String REMOVE_NOTIFICATION = "removeNotification";
    private static final String REMOVE_GROUPED_NOTIFICATIONS = "removeGroupedNotifications";

    private static final String ADD_EMAIL = "addEmail";
    private static final String REMOVE_EMAIL = "removeEmail";

    private static final String ADD_SMS = "addSms";
    private static final String REMOVE_SMS = "removeSms";

    private static final String SET_LOG_LEVEL = "setLogLevel";
    private static final String SET_ALERT_LEVEL = "setAlertLevel";

    private static final String SET_LOCATION_SHARED = "setLocationShared";
    private static final String IS_LOCATION_SHARED = "isLocationShared";
    private static final String REQUEST_LOCATION_PERMISSION = "requestLocationPermission";

    private static final String SET_PRIVACY_CONSENT_REQUIRED = "setPrivacyConsentRequired";
    private static final String SET_PRIVACY_CONSENT_GIVEN = "setPrivacyConsentGiven";

    private static final String ADD_TRIGGERS = "addTriggers";
    private static final String REMOVE_TRIGGERS = "removeTriggers";
    private static final String CLEAR_TRIGGERS = "clearTriggers";
    private static final String SET_PAUSED = "setPaused";
    private static final String IS_PAUSED = "isPaused";

    private static final String ADD_OUTCOME = "addOutcome";
    private static final String ADD_UNIQUE_OUTCOME = "addUniqueOutcome";
    private static final String ADD_OUTCOME_WITH_VALUE = "addOutcomeWithValue";

    private static final String ENTER_LIVE_ACTIVITY = "enterLiveActivity";
    private static final String EXIT_LIVE_ACTIVITY = "exitLiveActivity";
    private static final String SET_PUSH_TO_START_TOKEN = "setPushToStartToken";
    private static final String REMOVE_PUSH_TO_START_TOKEN = "removePushToStartToken";
    private static final String SETUP_DEFAULT_ACTIVITY = "setupDefaultLiveActivity";
    private static final String START_DEFAULT_LIVE_ACTIVITY = "startDefaultLiveActivity";
    private static final String TRACK_EVENT = "trackEvent";

    private static final HashMap<String, INotificationWillDisplayEvent> notificationWillDisplayCache = new HashMap<>();
    private static final HashMap<String, INotificationWillDisplayEvent> preventDefaultCache = new HashMap<>();

    private static CallbackContext jsInAppMessageWillDisplayCallback;
    private static CallbackContext jsInAppMessageDidDisplayCallBack;
    private static CallbackContext jsInAppMessageWillDismissCallback;
    private static CallbackContext jsInAppMessageDidDismissCallBack;
    private static CallbackContext jsInAppMessageClickedCallback;
    private static CallbackContext jsNotificationInForegroundCallBack;
    private static CallbackContext jsNotificationClickedCallback;

    private static boolean initDone;

    /**
     * N O T I F I C A T I O N    L I F E C Y C L E
     */
    public boolean addForegroundLifecycleListener(CallbackContext callbackContext) {
        jsNotificationInForegroundCallBack = callbackContext;
        return true;
    }

    @Override
    public void onWillDisplay(INotificationWillDisplayEvent event) {
        if (jsNotificationInForegroundCallBack != null) {
            try {
                INotification notification = event.getNotification();
                notificationWillDisplayCache.put(
                        notification.getNotificationId(), (INotificationWillDisplayEvent) event);

                event.preventDefault();

                JSONObject foregroundData = serializeNotification(notification);
                CallbackHelper.callbackSuccess(jsNotificationInForegroundCallBack, foregroundData);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    private boolean proceedWithWillDisplay(JSONArray data) {
        try {
            String notificationId = data.getString(0);
            INotificationWillDisplayEvent event = notificationWillDisplayCache.get(notificationId);
            if (event == null) {
                Logging.error(
                        "Could not find onWillDisplayNotification event for notification with id: " + notificationId,
                        null);
                return true;
            }
            if (this.preventDefaultCache.containsKey(notificationId)) {
                return true;
            }
            event.getNotification().display();
            return true;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return true;
    }

    private boolean displayNotification(JSONArray data) {
        try {
            String notificationId = data.getString(0);
            INotificationWillDisplayEvent event = notificationWillDisplayCache.get(notificationId);
            if (event == null) {
                Logging.error(
                        "Could not find onWillDisplayNotification event for notification with id: " + notificationId,
                        null);
                return true;
            }
            event.getNotification().display();
            return true;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return true;
    }

    private boolean preventDefault(JSONArray data) {
        try {
            String notificationId = data.getString(0);
            boolean shouldDiscard = data.getBoolean(1);

            INotificationWillDisplayEvent event = notificationWillDisplayCache.get(notificationId);
            if (event == null) {
                Logging.error(
                        "Could not find onWillDisplayNotification event for notification with id: " + notificationId,
                        null);
                return true;
            }
            event.preventDefault(shouldDiscard);
            this.preventDefaultCache.put(notificationId, event);
            return true;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * N O T I F I C A T I O N    C L I C K    L I S T E N E R
     */
    private boolean hasAddedNotificationClickListener = false;

    public boolean addNotificationClickListener(CallbackContext callbackContext) {
        jsNotificationClickedCallback = callbackContext;
        if (!this.hasAddedNotificationClickListener) {
            OneSignal.getNotifications().addClickListener(this);
            hasAddedNotificationClickListener = true;
        }
        return true;
    }

    @Override
    public void onClick(INotificationClickEvent event) {
        try {
            if (jsNotificationClickedCallback != null) {
                CallbackHelper.callbackSuccess(jsNotificationClickedCallback, serializeNotificationClickEvent(event));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * I N    A P P    M E S S A G E    C L I C K    L I S T E N E R
     */
    public boolean setInAppMessageClickHandler(CallbackContext callbackContext) {
        jsInAppMessageClickedCallback = callbackContext;
        return true;
    }

    @Override
    public void onClick(IInAppMessageClickEvent event) {
        try {
            if (jsInAppMessageClickedCallback != null) {
                CallbackHelper.callbackSuccess(jsInAppMessageClickedCallback, serializeInAppMessageClickEvent(event));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * I N    A P P    M E S S A G E    L I F E C Y C L E
     */
    @Override
    public void onWillDisplay(IInAppMessageWillDisplayEvent event) {
        if (jsInAppMessageWillDisplayCallback != null) {
            try {
                JSONObject onWillDisplayResult = new JSONObject();
                onWillDisplayResult.put("message", serializeInAppMessage(event.getMessage()));
                CallbackHelper.callbackSuccess(jsInAppMessageWillDisplayCallback, onWillDisplayResult);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onDidDisplay(IInAppMessageDidDisplayEvent event) {
        if (jsInAppMessageDidDisplayCallBack != null) {
            try {
                JSONObject onDidDisplayResult = new JSONObject();
                onDidDisplayResult.put("message", serializeInAppMessage(event.getMessage()));
                CallbackHelper.callbackSuccess(jsInAppMessageDidDisplayCallBack, onDidDisplayResult);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onWillDismiss(IInAppMessageWillDismissEvent event) {
        if (jsInAppMessageWillDismissCallback != null) {
            try {
                JSONObject onWillDismissResult = new JSONObject();
                onWillDismissResult.put("message", serializeInAppMessage(event.getMessage()));
                CallbackHelper.callbackSuccess(jsInAppMessageWillDismissCallback, onWillDismissResult);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onDidDismiss(IInAppMessageDidDismissEvent event) {
        if (jsInAppMessageDidDismissCallBack != null) {
            try {
                JSONObject onDidDismissResult = new JSONObject();
                onDidDismissResult.put("message", serializeInAppMessage(event.getMessage()));
                CallbackHelper.callbackSuccess(jsInAppMessageDidDismissCallBack, onDidDismissResult);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    public boolean setOnWillDisplayInAppMessageHandler(CallbackContext callbackContext) {
        jsInAppMessageWillDisplayCallback = callbackContext;
        return true;
    }

    public boolean setOnDidDisplayInAppMessageHandler(CallbackContext callbackContext) {
        jsInAppMessageDidDisplayCallBack = callbackContext;
        return true;
    }

    public boolean setOnWillDismissInAppMessageHandler(CallbackContext callbackContext) {
        jsInAppMessageWillDismissCallback = callbackContext;
        return true;
    }

    public boolean setOnDidDismissInAppMessageHandler(CallbackContext callbackContext) {
        jsInAppMessageDidDismissCallBack = callbackContext;
        return true;
    }

    /**
     * I N I T I A L I Z A T I O N
     */
    public boolean init(CallbackContext callbackContext, JSONArray data) {
        if (initDone) {
            Logging.debug("Already initialized the OneSignal Cordova SDK", null);
            return true;
        }

        initDone = true;
        OneSignalWrapper.setSdkType("cordova");
        OneSignalWrapper.setSdkVersion("050308");
        try {
            String appId = data.getString(0);
            OneSignal.initWithContext(this.cordova.getActivity(), appId);

            // add listeners
            OneSignal.getInAppMessages().addLifecycleListener(this);
            OneSignal.getInAppMessages().addClickListener(this);
            OneSignal.getNotifications().addForegroundLifecycleListener(this);

            CallbackHelper.callbackSuccessBoolean(callbackContext, true);
            return true;
        } catch (JSONException e) {
            Logging.error(TAG + "execute: Got JSON Exception " + e.getMessage(), null);
            return false;
        }
    }

    @Override
    public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {
        boolean result = false;

        switch (action) {
            case ADD_NOTIFICATION_CLICK_LISTENER:
                result = addNotificationClickListener(callbackContext);
                break;

            case ADD_FOREGROUND_LIFECYCLE_LISTENER:
                result = addForegroundLifecycleListener(callbackContext);
                break;

            case PROCEED_WITH_WILL_DISPLAY:
                result = proceedWithWillDisplay(data);
                break;

            case DISPLAY_NOTIFICATION:
                result = displayNotification(data);
                break;

            case PREVENT_DEFAULT:
                result = preventDefault(data);
                break;

            case SET_IN_APP_MESSAGE_CLICK_HANDLER:
                result = setInAppMessageClickHandler(callbackContext);
                break;

            case SET_ON_WILL_DISPLAY_IN_APP_MESSAGE_HANDLER:
                result = setOnWillDisplayInAppMessageHandler(callbackContext);
                break;

            case SET_ON_DID_DISPLAY_IN_APP_MESSAGE_HANDLER:
                result = setOnDidDisplayInAppMessageHandler(callbackContext);
                break;

            case SET_ON_WILL_DISMISS_IN_APP_MESSAGE_HANDLER:
                result = setOnWillDismissInAppMessageHandler(callbackContext);
                break;

            case SET_ON_DID_DISMISS_IN_APP_MESSAGE_HANDLER:
                result = setOnDidDismissInAppMessageHandler(callbackContext);
                break;

            case INIT:
                result = init(callbackContext, data);
                break;

            case SET_LANGUAGE:
                result = OneSignalController.setLanguage(data);
                break;

            case LOGIN:
                result = OneSignalController.login(data);
                break;

            case LOGOUT:
                result = OneSignalController.logout();
                break;

            case ADD_PERMISSION_OBSERVER:
                result = OneSignalObserverController.addPermissionObserver(callbackContext);
                break;

            case ADD_PUSH_SUBSCRIPTION_OBSERVER:
                result = OneSignalObserverController.addPushSubscriptionObserver(callbackContext);
                break;

            case ADD_USER_STATE_OBSERVER:
                result = OneSignalObserverController.addUserStateObserver(callbackContext);
                break;

            case GET_ONESIGNAL_ID:
                result = OneSignalController.getOnesignalId(callbackContext);
                break;

            case GET_EXTERNAL_ID:
                result = OneSignalController.getExternalId(callbackContext);
                break;

            case OPT_IN:
                result = OneSignalController.optInPushSubscription();
                break;

            case OPT_OUT:
                result = OneSignalController.optOutPushSubscription();
                break;

            case GET_ID:
                result = OneSignalController.getPushSubscriptionId(callbackContext);
                break;

            case GET_TOKEN:
                result = OneSignalController.getPushSubscriptionToken(callbackContext);
                break;

            case GET_OPTED_IN:
                result = OneSignalController.getPushSubscriptionOptedIn(callbackContext);
                break;

            case ADD_ALIASES:
                result = OneSignalController.addAliases(data);
                break;

            case REMOVE_ALIASES:
                result = OneSignalController.removeAliases(data);
                break;

            case ADD_TAGS:
                result = OneSignalController.addTags(data);
                break;

            case REMOVE_TAGS:
                result = OneSignalController.removeTags(data);
                break;

            case GET_TAGS:
                result = OneSignalController.getTags(callbackContext);
                break;

            case REGISTER_FOR_PROVISIONAL_AUTHORIZATION:
                result = OneSignalController.registerForProvisionalAuthorization();
                break;

            case REQUEST_PERMISSION:
                result = OneSignalController.requestPermission(callbackContext, data);
                break;

            case GET_PERMISSION_INTERNAL:
                result = OneSignalController.getPermissionInternal(callbackContext);
                break;

            case PERMISSION_NATIVE:
                result = OneSignalController.permissionNative(callbackContext);
                break;

            case CAN_REQUEST_PERMISSION:
                result = OneSignalController.canRequestPermission(callbackContext);
                break;

            case CLEAR_ALL_NOTIFICATIONS:
                result = OneSignalController.clearAllNotifications();
                break;

            case REMOVE_NOTIFICATION:
                result = OneSignalController.removeNotification(data);
                break;

            case REMOVE_GROUPED_NOTIFICATIONS:
                result = OneSignalController.removeGroupedNotifications(data);
                break;

            case SET_LOG_LEVEL:
                OneSignalController.setLogLevel(data);
                break;

            case SET_ALERT_LEVEL:
                OneSignalController.setAlertLevel(data);
                break;

            case ADD_EMAIL:
                result = OneSignalEmailController.addEmail(data);
                break;

            case REMOVE_EMAIL:
                result = OneSignalEmailController.removeEmail(data);
                break;

            case ADD_SMS:
                result = OneSignalSMSController.addSms(data);
                break;

            case REMOVE_SMS:
                result = OneSignalSMSController.removeSms(data);
                break;

            case REQUEST_LOCATION_PERMISSION:
                OneSignalController.requestLocationPermission();
                break;

            case SET_LOCATION_SHARED:
                OneSignalController.setLocationShared(data);
                break;

            case IS_LOCATION_SHARED:
                result = OneSignalController.isLocationShared(callbackContext);
                break;

            case SET_PRIVACY_CONSENT_REQUIRED:
                result = OneSignalController.setPrivacyConsentRequired(data);
                break;

            case SET_PRIVACY_CONSENT_GIVEN:
                result = OneSignalController.setPrivacyConsentGiven(data);
                break;

            case ADD_TRIGGERS:
                result = OneSignalInAppMessagingController.addTriggers(data);
                break;

            case REMOVE_TRIGGERS:
                result = OneSignalInAppMessagingController.removeTriggers(data);
                break;

            case CLEAR_TRIGGERS:
                result = OneSignalInAppMessagingController.clearTriggers();
                break;

            case SET_PAUSED:
                result = OneSignalInAppMessagingController.setPaused(data);
                break;

            case IS_PAUSED:
                result = OneSignalInAppMessagingController.isPaused(callbackContext);
                break;

            case ADD_OUTCOME:
                result = OneSignalOutcomeController.addOutcome(data);
                break;

            case ADD_UNIQUE_OUTCOME:
                result = OneSignalOutcomeController.addUniqueOutcome(data);
                break;

            case ADD_OUTCOME_WITH_VALUE:
                result = OneSignalOutcomeController.addOutcomeWithValue(data);
                break;

            case ENTER_LIVE_ACTIVITY:
                result = OneSignalController.enterLiveActivity();
                break;

            case EXIT_LIVE_ACTIVITY:
                result = OneSignalController.exitLiveActivity();
                break;

            case SET_PUSH_TO_START_TOKEN:
                result = OneSignalController.setPushToStartToken();
                break;

            case REMOVE_PUSH_TO_START_TOKEN:
                result = OneSignalController.removePushToStartToken();
                break;

            case SETUP_DEFAULT_ACTIVITY:
                result = OneSignalController.setupDefaultLiveActivity();
                break;

            case START_DEFAULT_LIVE_ACTIVITY:
                result = OneSignalController.startDefaultLiveActivity();
                break;

            case TRACK_EVENT:
                result = OneSignalController.trackEvent(data);
                break;

            default:
                Logging.error(TAG + "Invalid action : " + action, null);
                CallbackHelper.callbackError(callbackContext, "Invalid action : " + action);
        }
        return result;
    }

    /**
     * S E R I A L I Z E R S
     */
    private JSONObject serializeNotification(INotification notification) throws JSONException {
        JSONObject foregroundData = new JSONObject();

        foregroundData.put("body", notification.getBody());
        foregroundData.put("sound", notification.getSound());
        foregroundData.put("title", notification.getTitle());
        foregroundData.put("launchURL", notification.getLaunchURL());
        foregroundData.put("rawPayload", notification.getRawPayload());
        foregroundData.put("actionButtons", notification.getActionButtons());
        foregroundData.put("additionalData", notification.getAdditionalData());
        foregroundData.put("notificationId", notification.getNotificationId());
        foregroundData.put("groupKey", notification.getGroupKey());
        foregroundData.put("groupMessage", notification.getGroupMessage());
        foregroundData.put("groupedNotifications", notification.getGroupedNotifications());
        foregroundData.put("ledColor", notification.getLedColor());
        foregroundData.put("priority", notification.getPriority());
        foregroundData.put("smallIcon", notification.getSmallIcon());
        foregroundData.put("largeIcon", notification.getLargeIcon());
        foregroundData.put("bigPicture", notification.getBigPicture());
        foregroundData.put("collapseId", notification.getCollapseId());
        foregroundData.put("fromProjectNumber", notification.getFromProjectNumber());
        foregroundData.put("smallIconAccentColor", notification.getSmallIconAccentColor());
        foregroundData.put("lockScreenVisibility", notification.getLockScreenVisibility());
        foregroundData.put("androidNotificationId", notification.getAndroidNotificationId());

        return foregroundData;
    }

    private JSONObject serializeInAppMessage(IInAppMessage message) throws JSONException {
        JSONObject json = new JSONObject();
        json.put("messageId", message.getMessageId());
        return json;
    }

    private JSONObject serializeInAppMessageClickEvent(IInAppMessageClickEvent event) throws JSONException {
        JSONObject json = new JSONObject();
        JSONObject clickResultJson = new JSONObject();

        IInAppMessageClickResult result = event.getResult();
        clickResultJson.put("actionId", result.getActionId());
        clickResultJson.put("urlTarget", result.getUrlTarget());
        clickResultJson.put("url", result.getUrl());
        clickResultJson.put("closingMessage", result.getClosingMessage());

        json.put("result", clickResultJson);
        json.put("message", serializeInAppMessage(event.getMessage()));
        return json;
    }

    private JSONObject serializeNotificationClickEvent(INotificationClickEvent event) throws JSONException {
        JSONObject json = new JSONObject();
        JSONObject clickResultJson = new JSONObject();

        INotificationClickResult clickResult = event.getResult();
        clickResultJson.put("actionId", clickResult.getActionId());
        clickResultJson.put("url", clickResult.getUrl());

        json.put("notification", serializeNotification(event.getNotification()));
        json.put("result", clickResultJson);
        return json;
    }

    @Override
    public void onDestroy() {
        if (!initDone) {
            Logging.debug("OneSignal Cordova SDK not initialized yet. Could not remove listeners.", null);
            return;
        }

        hasAddedNotificationClickListener = false;
        OneSignal.getNotifications().removeClickListener(this);
        OneSignal.getNotifications().removeForegroundLifecycleListener(this);
        OneSignal.getInAppMessages().removeClickListener(this);
        OneSignal.getInAppMessages().removeLifecycleListener(this);
    }
}
