
package in.slanglabs;

import android.app.Application;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;

import com.facebook.react.bridge.Arguments;
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.ReadableType;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import in.slanglabs.assistants.base.BaseUI;
import in.slanglabs.assistants.payments.Action;
import in.slanglabs.assistants.payments.AssistantConfiguration;
import in.slanglabs.assistants.payments.AssistantError;
import in.slanglabs.assistants.payments.AssistantUI;
import in.slanglabs.assistants.payments.SlangPaymentsAssistant;
import in.slanglabs.assistants.payments.UserJourney.AssistantUserJourney;
import in.slanglabs.assistants.payments.UserJourney.BillPayments.BillInfo;
import in.slanglabs.assistants.payments.UserJourney.BillPayments.BillPaymentsAppState;
import in.slanglabs.assistants.payments.UserJourney.BillPayments.BillPaymentsJourney;
import in.slanglabs.assistants.payments.UserJourney.BillPayments.PaymentCompleteAppState;
import in.slanglabs.assistants.payments.UserJourney.Navigation.NavigationAppState;
import in.slanglabs.assistants.payments.UserJourney.Navigation.NavigationCompleteAppState;
import in.slanglabs.assistants.payments.UserJourney.Navigation.NavigationInfo;
import in.slanglabs.assistants.payments.UserJourney.Navigation.NavigationUserJourney;
import in.slanglabs.assistants.payments.UserJourney.Transaction.TransactionAppState;
import in.slanglabs.assistants.payments.UserJourney.Transaction.TransactionCompleteAppState;
import in.slanglabs.assistants.payments.UserJourney.Transaction.TransactionInfo;
import in.slanglabs.assistants.payments.UserJourney.Transaction.TransactionUserJourney;
import in.slanglabs.assistants.payments.UserJourney.UnsupportedAppState;
import in.slanglabs.assistants.payments.UserJourney.WaitingAppState;

public class RNSlangPaymentsAssistantModule extends ReactContextBaseJavaModule {

    private final ReactApplicationContext mReactContext;

    private static final String TAG = "RNSlangRetailAssistant";
    private static final String CONFIG_ASSISTANT_ID = "assistantId";
    private static final String CONFIG_API_KEY = "apiKey";
    private static final String CONFIG_LOCALE = "locale";
    private static final String CONFIG_REQUESTED_LOCALES = "requestedLocales";
    private static final String CONFIG_TRIGGER_POSITION = "triggerPosition";
    private static final String CONFIG_TRIGGER_STYLE = "triggerStyle";
    private static final String CONFIG_CUSTOM_TRIGGER_ENABLE = "enableCustomTrigger";
    private static final String CONFIG_ONBOARDING_INFO_TITLE = "onBoardingInfoTitle";
    private static final String CONFIG_ONBOARDING_INFO_DESCRIPTION = "onBoardingInfoDescription";
    private static final String CONFIG_BRAND_COLOR = "brandColor";
    private static final String CONFIG_ENVIRONMENT = "environment";

    private BillPaymentsJourney mBillPaymentUserJourney;
    private TransactionUserJourney mTransactionUserJourney;
    private NavigationUserJourney mNavigationalUserJourney;

    private PaymentCompleteAppState.Condition mBillPaymentAppStateCondition;
    private TransactionCompleteAppState.Condition mTransactionAppStateCondition;
    private NavigationCompleteAppState.Condition mNavigationAppStateCondition;

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

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

    /**
     * Initialize Slang
     *
     * @param configOptions Configurations
     */
    @ReactMethod
    public void initialize(ReadableMap configOptions) {
        Log.e(TAG, "initialize");
        RNSlangUtils.setConfigOptions(configOptions);
        try {
            AssistantConfiguration.Builder configBuilder = new AssistantConfiguration.Builder()
                    .setAssistantId(RNSlangUtils.getStringConfig(CONFIG_ASSISTANT_ID))
                    .setAPIKey(RNSlangUtils.getStringConfig(CONFIG_API_KEY))
                    .setDefaultLocale(RNSlangLocaleMap.getDefaultLocale(RNSlangUtils.getStringConfig(
                            CONFIG_LOCALE)))
                    .setRequestedLocales(
                            RNSlangLocaleMap.getRequestedLocales(RNSlangUtils.getStringListConfig(
                                    CONFIG_REQUESTED_LOCALES)))
                    .enableCustomTrigger(RNSlangUtils.getBooleanConfig(CONFIG_CUSTOM_TRIGGER_ENABLE))
                    .setTriggerStyle(RNSlangUtils.getTriggerStyle(CONFIG_TRIGGER_STYLE))
                    .setUIPosition(RNSlangUtils.getAssistantUIConfig(CONFIG_TRIGGER_POSITION))
                    .setOnboardingInfoTitle(RNSlangUtils.getLocaleStringMapConfig(CONFIG_ONBOARDING_INFO_TITLE))
                    .setOnboardingInfoDescription(RNSlangUtils.getLocaleStringMapConfig(CONFIG_ONBOARDING_INFO_DESCRIPTION))
                    .setEnvironment(RNSlangUtils.getEnvironment(CONFIG_ENVIRONMENT));

            if (RNSlangUtils.configHasKey(CONFIG_BRAND_COLOR)) {
                configBuilder.setBrandColor(RNSlangUtils.getStringConfig(CONFIG_BRAND_COLOR));
            }

            if (mReactContext.getApplicationContext() instanceof Application) {
                SlangPaymentsAssistant.initialize((Application) mReactContext.getApplicationContext(), configBuilder.build());
            } else if (getCurrentActivity() != null) {
                SlangPaymentsAssistant.initialize(getCurrentActivity().getApplication(), configBuilder.build());
            } else {
                WritableMap params = Arguments.createMap();
                params.putString("type", "Invalid call to initialize");
                sendEvent("onAssistantInitFailure", params);
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setAction() {
        try {
            SlangPaymentsAssistant.setAction(new Action() {
                @Override
                public NavigationAppState onNavigation(final NavigationInfo navigationInfo, NavigationUserJourney navigationUserJourney) {
                    mNavigationalUserJourney = navigationUserJourney;
                    new Handler().post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                WritableMap navigationInfoMap = RNSlangUtils.mapNavigationInfo(navigationInfo);
                                sendEvent("onNavigation", navigationInfoMap);
                                Log.d(TAG, String.valueOf(navigationInfo));
                            } catch (Exception exception) {
                                sendAssistantError(exception);
                            }
                        }
                    });
                    return new WaitingAppState();
                }

                @Override
                public TransactionAppState onTransaction(final TransactionInfo transactionInfo, TransactionUserJourney transactionUserJourney) {
                    mTransactionUserJourney = transactionUserJourney;
                    new Handler().post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                WritableMap transactionInfoMap = RNSlangUtils.mapTransactionInfo(transactionInfo);
                                sendEvent("onTransaction", transactionInfoMap);
                                Log.d(TAG, String.valueOf(transactionInfoMap));
                            } catch (Exception exception) {
                                sendAssistantError(exception);
                            }
                        }
                    });
                    return new WaitingAppState();
                }

                @Override
                public BillPaymentsAppState onBillPayment(final BillInfo billInfo, BillPaymentsJourney billPaymentsJourney) {
                    mBillPaymentUserJourney = billPaymentsJourney;
                    new Handler().post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                WritableMap billInfoMap = RNSlangUtils.mapBillInfo(billInfo);
                                sendEvent("onBillPayment", billInfoMap);
                                Log.d(TAG, String.valueOf(billInfoMap));
                            } catch (Exception exception) {
                                sendAssistantError(exception);
                            }
                        }
                    });
                    return new WaitingAppState();
                }

                @Override
                public void onAssistantError(AssistantError assistantError) {
                    Log.d(TAG, String.valueOf(assistantError));
                    WritableMap params = Arguments.createMap();
                    params.putInt("type", assistantError.getType());
                    sendEvent("onAssistantError", params);
                }
            });

        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setLifecycleObserver() {
        try {
            SlangPaymentsAssistant.setLifecycleObserver(new SlangPaymentsAssistant.LifecycleObserver() {
                @Override
                public void onAssistantInitSuccess() {
                    sendEvent("onAssistantInitSuccess", Arguments.createMap());
                }

                @Override
                public void onAssistantInitFailure(String s) {
                    Log.d(TAG, s);
                    WritableMap params = Arguments.createMap();
                    params.putString("type", s);
                    sendEvent("onAssistantInitFailure", params);
                }

                @Override
                public void onAssistantInvoked() {
                    sendEvent("onAssistantInvoked", Arguments.createMap());
                }

                @Override
                public void onAssistantClosed(boolean b) {
                    WritableMap params = Arguments.createMap();
                    params.putBoolean("isCancelled", b);
                    sendEvent("onAssistantClosed", params);
                }

                @Override
                public void onAssistantLocaleChanged(Locale locale) {
                    WritableMap localeMap = Arguments.createMap();
                    localeMap.putString("country", locale.getCountry().toUpperCase());
                    localeMap.putString("language", locale.getLanguage());
                    sendEvent("onAssistantLocaleChanged", localeMap);
                }

                @Override
                public boolean onUnrecognisedUtterance(String s) {
                    WritableMap params = Arguments.createMap();
                    params.putString("utterance", s);
                    sendEvent("onUnrecognisedUtterance", params);
                    return false;
                }

                @Override
                public void onUtteranceDetected(String s) {
                    WritableMap params = Arguments.createMap();
                    params.putString("utterance", s);
                    sendEvent("onUtteranceDetected", params);
                }

                @Override
                public void onOnboardingSuccess() {
                    sendEvent("onOnboardingSuccess", Arguments.createMap());
                }

                @Override
                public void onOnboardingFailure() {
                    sendEvent("onOnboardingFailure", Arguments.createMap());
                }

                @Override
                public void onMicPermissionDenied() {
                    sendEvent("onMicPermissionDenied", Arguments.createMap());
                }

                @Override
                public void onMicPermissionGranted() {
                    sendEvent("onMicPermissionGranted", Arguments.createMap());
                }

            });
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void prepareActiveTransactionUserJourney() {
    }

    @ReactMethod
    public void prepareActiveBillPaymentUserJourney() {
    }

    @ReactMethod
    public void prepareActiveNavigationUserJourney() {
    }

    @ReactMethod
    public void startConversation(String userJourney) {
        Log.d(TAG, "startConversation : " + userJourney);
        try {
            if (getCurrentActivity() != null) {
                try {
                    SlangPaymentsAssistant.startConversation(
                            AssistantUserJourney.fromString(userJourney),
                            getCurrentActivity()
                    );
                } catch (Exception exception) {
                    sendAssistantError(exception);
                }
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void notifyNonVoiceTransaction(final String name, final String amount, String action) {
        Log.d(TAG, "notifyNonVoiceTransaction : " + name + ", " + amount + ", " + action);
        try {
            TransactionInfo.TransactionAction transactionAction = TransactionInfo.TransactionAction.fromString(action);
            HashMap<String, String> transactionInfo = new HashMap<String, String>() {
                {
                    put(SlangPaymentsAssistant.TRANSACTION_NAME, name);
                    put(SlangPaymentsAssistant.TRANSACTION_AMOUNT, amount);
                }
            };
            if (transactionAction == TransactionInfo.TransactionAction.REQUEST) {
                SlangPaymentsAssistant.notifyNonVoiceTransaction(transactionInfo, new TransactionCompleteAppState(TransactionCompleteAppState.REQUEST_SUCCESS));
            }
            else if (transactionAction == TransactionInfo.TransactionAction.SEND) {
                SlangPaymentsAssistant.notifyNonVoiceTransaction(transactionInfo, new TransactionCompleteAppState(TransactionCompleteAppState.SEND_SUCCESS));
            }
            else {
                SlangPaymentsAssistant.notifyNonVoiceTransaction(transactionInfo, new TransactionCompleteAppState(TransactionCompleteAppState.SUCCESS));
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTriggerSize(int width, int height) {
        try {
            SlangPaymentsAssistant.getUI().setTriggerSize(width, height);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTriggerImageResource(String uriString) {
        Log.d(TAG, "setTriggerImageResource: " + uriString);
        try {
            // Debug
            if (uriString.startsWith("http")) {
                URL url = new URL(uriString);
                Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
                Drawable drawable = new BitmapDrawable(mReactContext.getResources(), image);
                SlangPaymentsAssistant.getUI().setTriggerImageDrawable(drawable);
            } else {
                // Release
                int resourceId = mReactContext.getResources().getIdentifier(uriString, "drawable", mReactContext.getPackageName());
                Bitmap image = BitmapFactory.decodeResource(mReactContext.getResources(), resourceId);
                SlangPaymentsAssistant.getUI().setTriggerImageResource(resourceId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ReactMethod
    public void setTransactionSuccess() {
        Log.d(TAG, "setTransactionSuccess");
        try {
            if (mTransactionUserJourney != null) {
                mTransactionAppStateCondition = TransactionCompleteAppState.SUCCESS;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTransactionFailure() {
        Log.d(TAG, "setTransactionFailure");
        try {
            if (mTransactionUserJourney != null) {
                mTransactionAppStateCondition = TransactionCompleteAppState.FAILURE;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTransactionNameRequired() {
        Log.d(TAG, "setTransactionNameRequired");
        try {
            if (mTransactionUserJourney != null) {
                mTransactionAppStateCondition = TransactionCompleteAppState.NAME_REQUIRED;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTransactionNameAmbiguous() {
        Log.d(TAG, "setTransactionNameAmbiguous");
        try {
            if (mTransactionUserJourney != null) {
                mTransactionAppStateCondition = TransactionCompleteAppState.NAME_AMBIGUOUS;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTransactionNameNotFound() {
        Log.d(TAG, "setTransactionNameNotFound");
        try {
            if (mTransactionUserJourney != null) {
                mTransactionAppStateCondition = TransactionCompleteAppState.NAME_NOT_FOUND;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTransactionAmountRequired() {
        Log.d(TAG, "setAmountRequired");
        try {
            if (mTransactionUserJourney != null) {
                mTransactionAppStateCondition = TransactionCompleteAppState.AMOUNT_REQUIRED;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTransactionActionRequired() {
        Log.d(TAG, "setTransactionActionRequired");
        try {
            if (mTransactionUserJourney != null) {
                mTransactionAppStateCondition = TransactionCompleteAppState.ACTION_REQUIRED;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void notifyTransactionActionCompleted(final String transactionAppState) {
        Log.d(TAG, "notifyTransactionActionCompleted: " + transactionAppState);

        if (mTransactionUserJourney == null) {
            return;
        }

        try {
            if (transactionAppState.equals("unsupported")) {
                mTransactionUserJourney.notifyAppState(new UnsupportedAppState());
            } else if (!transactionAppState.equals("waiting") && mTransactionAppStateCondition != null) {
                mTransactionUserJourney.notifyAppState(new TransactionCompleteAppState(mTransactionAppStateCondition));
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }

        mTransactionAppStateCondition = null;
    }

    @ReactMethod
    public void setBillPaymentSuccess() {
        Log.d(TAG, "setBillPaymentSuccess");
        try {
            if (mBillPaymentUserJourney != null) {
                mBillPaymentAppStateCondition = PaymentCompleteAppState.SUCCESS;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setBillPaymentFailure() {
        Log.d(TAG, "setBillPaymentFailure");
        try {
            if (mBillPaymentUserJourney != null) {
                mBillPaymentAppStateCondition = PaymentCompleteAppState.FAILURE;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setBillPaymentBillTypeRequired() {
        Log.d(TAG, "setBillPaymentBillTypeRequired");
        try {
            if (mBillPaymentUserJourney != null) {
                mBillPaymentAppStateCondition = PaymentCompleteAppState.BILL_TYPE_REQUIRED;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setBillPaymentBillTypeNotFound() {
        Log.d(TAG, "setBillPaymentBillTypeNotFound");
        try {
            if (mBillPaymentUserJourney != null) {
                mBillPaymentAppStateCondition = PaymentCompleteAppState.BILL_TYPE_NOT_FOUND;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void notifyBillPaymentActionCompleted(final String billPaymentAppState) {
        Log.d(TAG, "notifyBillPaymentActionCompleted: " + billPaymentAppState);

        if (mBillPaymentUserJourney == null) {
            return;
        }

        try {
            if (billPaymentAppState.equals("unsupported")) {
                mTransactionUserJourney.notifyAppState(new UnsupportedAppState());
            } else if (!billPaymentAppState.equals("waiting") && mBillPaymentAppStateCondition != null) {
                mBillPaymentUserJourney.notifyAppState(new PaymentCompleteAppState(mBillPaymentAppStateCondition));
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }

        mTransactionAppStateCondition = null;
    }

    @ReactMethod
    public void setNavigationSuccess() {
        Log.d(TAG, "setNavigationSuccess");
        try {
            if (mNavigationalUserJourney != null) {
                mNavigationAppStateCondition = NavigationCompleteAppState.SUCCESS;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setNavigationFailure() {
        Log.d(TAG, "setNavigationFailure");
        try {
            if (mNavigationalUserJourney != null) {
                mNavigationAppStateCondition = NavigationCompleteAppState.FAILURE;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setNavigationTargetRequired() {
        Log.d(TAG, "setNavigationTargetRequired");
        try {
            if (mNavigationalUserJourney != null) {
                mNavigationAppStateCondition = NavigationCompleteAppState.TARGET_REQUIRED;
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void notifyNavigationActionCompleted(final String navigationAppState) {
        Log.d(TAG, "notifyNavigationActionCompleted: " + navigationAppState);

        if (mNavigationalUserJourney == null) {
            return;
        }

        try {
            if (navigationAppState.equals("unsupported")) {
                mNavigationalUserJourney.notifyAppState(new UnsupportedAppState());
            } else if (!navigationAppState.equals("waiting") && mNavigationAppStateCondition != null) {
                mNavigationalUserJourney.notifyAppState(
                        new NavigationCompleteAppState(mNavigationAppStateCondition)
                );
            }
        } catch (Exception exception) {
            sendAssistantError(exception);
        }

        mNavigationAppStateCondition = null;
    }

    @ReactMethod
    public void setUserJourneyToContinue(String currentUserJourney,
                                         String userJourneyToContinue, boolean isSpoken) {
        Log.d(TAG, "setUserJourneyToContinue");
    }

    @ReactMethod
    public void clearUserJourneyToContinue(String currentUserJourney) {
        Log.d(TAG, "clearUserJourneyToContinue");
    }

    @ReactMethod
    public void showTrigger() {
        if (getCurrentActivity() != null) {
            try {
                SlangPaymentsAssistant.getUI().showTrigger(getCurrentActivity());
            } catch (Exception exception) {
                sendAssistantError(exception);
            }
        }
    }

    @ReactMethod
    public void hideTrigger() {
        if (getCurrentActivity() != null) {
            try {
                SlangPaymentsAssistant.getUI().hideTrigger(getCurrentActivity());
            } catch (Exception exception) {
                sendAssistantError(exception);
            }
        }
    }

    @ReactMethod
    public void collapseTrigger() {
        if (getCurrentActivity() != null) {
            try {
                SlangPaymentsAssistant.getUI().collapseTrigger();
            } catch (Exception exception) {
                sendAssistantError(exception);
            }
        }
    }

    @ReactMethod
    public void expandTrigger() {
        if (getCurrentActivity() != null) {
            try {
                SlangPaymentsAssistant.getUI().expandTrigger();
            } catch (Exception exception) {
                sendAssistantError(exception);
            }
        }
    }

    @ReactMethod
    public void setTriggerText(ReadableMap triggerText) {
        Log.d(TAG, String.format(
                Locale.ENGLISH, "setTriggerText : %s", triggerText));
        if (getCurrentActivity() != null) {
            try {
                Map<Locale, String> triggerTextMap = RNSlangUtils.convertToLocaleStringMap(triggerText);
                SlangPaymentsAssistant.getUI().setTriggerText(triggerTextMap);
            } catch (Exception exception) {
                sendAssistantError(exception);
            }
        }
    }

    @ReactMethod
    public void setUserProperties(ReadableMap rnUserProperties) {
        Log.d(TAG, String.format(
                Locale.ENGLISH, "UserProperties : %s", rnUserProperties));
        try {
            Map<String, String> userPropertiesInfoMap = RNSlangUtils.convertReadableMapToMap(rnUserProperties);
            SlangPaymentsAssistant.setUserProperties(userPropertiesInfoMap);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    void notifyNonVoiceUserJourney(String userJourney, ReadableMap userJourneyInfo) {
    }

    @ReactMethod
    void setAppDefaultUserJourney(String userJourney) {
    }

    @ReactMethod
    void setAppDefaultSubDomain(String appSubDomain) {
    }

    @ReactMethod
    public void setBackgroundColorGradient(ReadableArray colors) {
        try {
            String[] backgroundColorGradients = new String[colors.size()];
            for (int i = 0; i < colors.size(); i++) {
                String color = "";
                if (colors.getType(i) == ReadableType.String) {
                    color = colors.getString(i);
                }
                backgroundColorGradients[i] = color;
            }
            SlangPaymentsAssistant.getUI().setBackgroundColorGradient(backgroundColorGradients);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setWaveColorGradient(ReadableArray colors) {
        try {
            String[] foregroundColorGradients = new String[colors.size()];
            for (int i = 0; i < colors.size(); i++) {
                String color = "";
                if (colors.getType(i) == ReadableType.String) {
                    color = colors.getString(i);
                }
                foregroundColorGradients[i] = color;
            }
            SlangPaymentsAssistant.getUI().setForegroundColorGradient(foregroundColorGradients);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTextColor(String color) {
        try {
            SlangPaymentsAssistant.getUI().setTextColor(color);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setSecondaryTextColor(String color) {
        try {
            SlangPaymentsAssistant.getUI().setSecondaryTextColor(color);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTextHighlightColor(String color) {
        try {
            SlangPaymentsAssistant.getUI().setTextHighlightColor(color);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setSettingsButtonBackgroundColor(String color) {
        try {
            SlangPaymentsAssistant.getUI().setSettingsButtonBackgroundColor(color);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setControlButtonBackgroundColor(String color) {
        try {
            SlangPaymentsAssistant.getUI().setControlButtonBackgroundColor(color);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    public void setTheme(String theme) {
        try {
            BaseUI.BaseTheme baseTheme = AssistantUI.Theme.LIGHT;
            if ("DARK".equals(theme)) {
                baseTheme = AssistantUI.Theme.DARK;
            }
            SlangPaymentsAssistant.getUI().setTheme(baseTheme);
        } catch (Exception exception) {
            sendAssistantError(exception);
        }
    }

    @ReactMethod
    void disableTransactionUserJourneyContext() {
    }

    @ReactMethod
    void disableBillPaymentUserJourneyContext() {
    }

    @ReactMethod
    void disableNavigationUserJourneyContext() {
    }

    private void sendAssistantError(Exception exception) {
        WritableMap params = Arguments.createMap();
        params.putString("type", exception.getMessage());
        sendEvent("onAssistantError", params);
    }

    private void sendEvent(String name, WritableMap params) {
        mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(name, params);
    }
}