package in.slanglabs;

import android.util.Log;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.WritableMap;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Locale;

import javax.annotation.Nullable;

import in.slanglabs.assistants.base.AssistantUIPosition;
import in.slanglabs.assistants.payments.AssistantTriggerStyle;
import in.slanglabs.assistants.payments.SlangPaymentsAssistant;
import in.slanglabs.assistants.payments.UserJourney.BillPayments.BillInfo;
import in.slanglabs.assistants.payments.UserJourney.Navigation.NavigationInfo;
import in.slanglabs.assistants.payments.UserJourney.Transaction.TransactionInfo;

public class RNSlangUtils {

    private static String TAG = "RNSlangUtils";
    private static ReadableMap mConfigOptions;

    static void setConfigOptions(ReadableMap configOptions) {
        mConfigOptions = configOptions;
    }

    static WritableMap mapNavigationInfo(NavigationInfo navigationInfo) {
        WritableMap navigationInfoMap = Arguments.createMap();
        if (navigationInfo != null) {
            navigationInfoMap.putString("target", navigationInfo.getTarget());
        }
        return navigationInfoMap;
    }

    static WritableMap mapTransactionInfo(@Nullable TransactionInfo transactionInfo) {
        WritableMap transactionInfoMap = Arguments.createMap();
        if (transactionInfo != null) {
            transactionInfoMap.putString("name",transactionInfo.getName());
            if (transactionInfo.getTransactionAction() != null) {
                transactionInfoMap.putString("transactionAction", transactionInfo.getTransactionAction().name());
            }
            transactionInfoMap.putMap("amount", mapAmount(transactionInfo.getAmount()));
        }
        return transactionInfoMap;
    }

    static WritableMap mapBillInfo(@Nullable BillInfo billInfo) {
        WritableMap billInfoMap = Arguments.createMap();
        if (billInfo != null) {
            billInfoMap.putString("type",billInfo.getBillType());
        }
        return billInfoMap;
    }

    static String getStringConfig(String key) {
        try {
            return mConfigOptions != null && mConfigOptions.hasKey(key) ?
                    mConfigOptions.getString(key) : null;
        } catch (Exception e) {
            Log.d(TAG, "mConfigOptions encountered an error");
        }

        return null;
    }

    static boolean configHasKey(String key) {
        return mConfigOptions != null && mConfigOptions.hasKey(key);
    }

    static boolean getBooleanConfig(String key) {
        try {
            return (mConfigOptions != null && mConfigOptions.hasKey(key)) &&
                    mConfigOptions.getBoolean(key);
        } catch (Exception e) {
            Log.d(TAG, "mConfigOptions encountered an error");
        }

        return false;
    }

    static List<String> getStringListConfig(String key) {
        if (mConfigOptions == null || !mConfigOptions.hasKey(key))
            return null;

        try {
            ReadableArray stringArray = mConfigOptions.getArray(key);
            if (null == stringArray || stringArray.size() == 0)
                return null;

            List<String> stringList = new ArrayList<>(stringArray.size());
            for (int i = 0; i < stringArray.size(); i++) {
                stringList.add(stringArray.getString(i));
            }
            return stringList;
        } catch (Exception e) {
            Log.d(TAG, "mConfigOptions encountered an error");
        }

        return null;
    }

    static SlangPaymentsAssistant.Environment getEnvironment(String key) {
        if (!configHasKey(key)) {
            return SlangPaymentsAssistant.Environment.STAGING;
        }
        try {
            if ("PRODUCTION".equals(getStringConfig(key))) {
                return SlangPaymentsAssistant.Environment.PRODUCTION;
            }
            return SlangPaymentsAssistant.Environment.STAGING;
        } catch (Exception e) {
            Log.d(TAG, "mConfigOptions encountered an error");
            return SlangPaymentsAssistant.Environment.STAGING;
        }
    }

    static AssistantTriggerStyle getTriggerStyle(String key) {
        if (!configHasKey(key)) {
            return AssistantTriggerStyle.DEFAULT;
        }
        try {
            if ("DEFAULT".equals(getStringConfig(key))) {
                return AssistantTriggerStyle.DEFAULT;
            }
            return AssistantTriggerStyle.FLAT;
        } catch (Exception e) {
            Log.d(TAG, "mConfigOptions encountered an error");
            return AssistantTriggerStyle.DEFAULT;
        }
    }

    static Map<Locale, String> getLocaleStringMapConfig(String key) {
        if (mConfigOptions == null || !mConfigOptions.hasKey(key))
            return null;
        ReadableMap stringMap = mConfigOptions.getMap(key);
        return convertToLocaleStringMap(stringMap);
    }

    static Map<Locale, String> convertToLocaleStringMap(ReadableMap stringMap) {
        if (null == stringMap) return null;
        ReadableMapKeySetIterator iterator = stringMap.keySetIterator();
        HashMap<Locale, String> localeStringMap = new HashMap<>();
        while (iterator.hasNextKey()) {
            String currentKey = iterator.nextKey();
            Locale locale = RNSlangLocaleMap.getLocale(currentKey);
            if (locale != null) {
                String value = stringMap.getString(currentKey);
                if (value != null) {
                    localeStringMap.put(locale, value);
                }
            }
        }

        return localeStringMap;
    }

    static AssistantUIPosition getAssistantUIConfig(String key) {
        in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition uiPosition
                = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.BOTTOM_CENTER;
        in.slanglabs.assistants.payments.AssistantUIPosition assistantUIPosition
                = new in.slanglabs.assistants.payments.AssistantUIPosition.Builder()
                .setBaseUIPosition(uiPosition)
                .setIsDraggable(false)
                .setIsForcedAtStartup(false)
                .build();

        if (mConfigOptions == null || !mConfigOptions.hasKey(key))
            return assistantUIPosition;

        try {
            ReadableMap assistantUIMap = mConfigOptions.getMap(key);
            if (null == assistantUIMap)
                return assistantUIPosition;
            String baseUIPosition = assistantUIMap.getString("baseUIPosition");
            switch (baseUIPosition != null ? baseUIPosition : "") {
                case "BOTTOM_LEFT":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.BOTTOM_LEFT;
                    break;
                case "CENTER_LEFT":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.CENTER_LEFT;
                    break;
                case "CENTER":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.CENTER;
                    break;
                case "CENTER_RIGHT":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.CENTER_RIGHT;
                    break;
                case "TOP_LEFT":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.TOP_LEFT;
                    break;
                case "TOP_CENTER":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.TOP_CENTER;
                    break;
                case "TOP_RIGHT":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.TOP_RIGHT;
                    break;
                case "BOTTOM_RIGHT":
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.BOTTOM_RIGHT;
                    break;
                default:
                    uiPosition = in.slanglabs.assistants.payments.AssistantUIPosition.UIPosition.BOTTOM_CENTER;
            }
            int offsetX = assistantUIMap.getInt("offsetX");
            int offsetY = assistantUIMap.getInt("offsetY");
            boolean draggable = assistantUIMap.getBoolean("draggable");
            boolean forcedAtStartup = assistantUIMap.getBoolean("forcedAtStartup");
            assistantUIPosition = new in.slanglabs.assistants.payments.AssistantUIPosition.Builder()
                    .setBaseUIPosition(uiPosition)
                    .setOffsetX(offsetX)
                    .setOffsetY(offsetY)
                    .setIsDraggable(draggable)
                    .setIsForcedAtStartup(forcedAtStartup)
                    .build();
            return assistantUIPosition;
        } catch (Exception e) {
            Log.d(TAG, "mConfigOptions encountered an error");
            return assistantUIPosition;
        }
    }

    static Map<String, String> convertReadableMapToMap(ReadableMap map) {
        Map<String, String> userJourneyInfoMap = new HashMap<>();
        if (null != map && map.toHashMap().size() > 0) {
            for (ReadableMapKeySetIterator it = map.keySetIterator(); it.hasNextKey(); ) {
                String key = it.nextKey();
                String value;
                switch (map.getType(key)) {
                    case Number:
                        value = String.valueOf(map.getDouble(key));
                        break;
                    case String:
                        value = map.getString(key);
                        break;
                    case Boolean:
                        value = Boolean.toString(map.getBoolean(key));
                        break;
                    default:
                        value = "";
                }
                userJourneyInfoMap.put(key, value != null ? value : "");
            }
        }
        return userJourneyInfoMap;
    }

    static WritableMap mapAmount(@Nullable TransactionInfo.Amount amount) {
        WritableMap amountInfoMap = Arguments.createMap();
        if (amount != null) {
            amountInfoMap.putDouble("amount", amount.getAmount());
            amountInfoMap.putString("currency", amount.getCurrency().name());
        }
        return amountInfoMap;
    }

}