package com.mobify.astro.plugins;

import android.os.Bundle;
import android.support.annotation.NonNull;

import com.mobify.astro.AstroActivity;
import com.mobify.astro.AstroException;
import com.mobify.astro.AstroPlugin;
import com.mobify.astro.PluginResolver;
import com.mobify.astro.dialogs.DialogManager;
import com.mobify.astro.messaging.EventRegistrar;
import com.mobify.astro.messaging.MessageSender;
import com.mobify.astro.messaging.RpcResponse;
import com.mobify.astro.messaging.annotations.AsyncRpcMethod;
import com.mobify.astro.messaging.annotations.RpcMethod;

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

import java.util.ArrayList;

public class ListSelectPlugin extends AstroPlugin {
    private static final String TAG = ListSelectPlugin.class.getName();

    final int REQUEST_CODE = Math.abs(hashCode());

    protected DialogManager dialogManager;
    protected Bundle bundle;

    public static final String KEY_TITLE = "list_title";
    public static final String KEY_CANCEL_BUTTON = "list_cancelButton";
    public static final String KEY_CANCELABLE = "list_cancelable";

    protected ArrayList<ListItem> list = new ArrayList<>();
    protected boolean cancelable = true;

    public static class ListItem {
        public String id;
        public String labelKey;
        public String label;

        public ListItem(String id, String labelKey) {
            this.id = id;
            this.labelKey = labelKey;
            this.label = labelKey;
        }
    }

    class ListSelectPluginException extends AstroException {
        ListSelectPluginException(String message) { super(TAG + ": " + message); }
    }

    public ListSelectPlugin(@NonNull AstroActivity activity, @NonNull PluginResolver pluginResolver,
                            @NonNull EventRegistrar eventRegistrar, @NonNull MessageSender messageSender) {
        super(activity, pluginResolver, eventRegistrar, messageSender);

        dialogManager = activity.getDialogManager();
        bundle = new Bundle();

        bundle.putString(KEY_CANCEL_BUTTON, "list_cancel");
    }

    public ListItem parseItem(JSONObject item) throws Exception {
        if (!item.has("id") || !item.has("label")) {
            throw new ListSelectPluginException("List item " + item + " requires an id and label");
        }

        return new ListItem(item.getString("id"), item.getString("label"));
    }

    @RpcMethod(methodName = "setTitle", parameterNames = {"title"})
    public void setTitle(String title) {
        bundle.putString(KEY_TITLE, title);
    }

    @RpcMethod(methodName = "setList", parameterNames = {"list"})
    public void setList(JSONArray list) throws Exception {
        this.list.clear();
        for(int i = 0; i < list.length(); i++) {
            ListItem item = parseItem(list.getJSONObject(i));
            if (item == null) {
                break;
            }
            this.list.add(item);
        }
    }

    @RpcMethod(methodName = "addItem", parameterNames = {"item"})
    public void addItem(JSONObject item) throws Exception {
        list.add(parseItem(item));
    }

    @RpcMethod(methodName = "setCancelable", parameterNames = {"cancelable"})
    public void setCancelable(boolean cancelable) {
        this.cancelable = cancelable;
    }

    @AsyncRpcMethod(methodName = "show", parameterNames = "options")
    public void show(final RpcResponse response, JSONObject options) throws Exception {

        if (list.size() == 0) {
            throw new ListSelectPluginException("List Select must contain at least one item");
        }

        // Localize ListItem labels
        for (ListItem item : list) {
            item.label = activity.getLocalizationUtilities().translate(item.labelKey);
        }

        bundle.putBoolean(KEY_CANCELABLE, cancelable);
        dialogManager.showListSelect(getLocalizedBundle(), list, this.activity, response, REQUEST_CODE);
    }

    protected Bundle getLocalizedBundle() {
        Bundle localizedBundle = new Bundle();
        localizedBundle = addLocalizedStringForKey(KEY_CANCEL_BUTTON, localizedBundle);
        localizedBundle = addLocalizedStringForKey(KEY_TITLE, localizedBundle);
        localizedBundle.putBoolean(KEY_CANCELABLE, cancelable);
        return localizedBundle;
    }

    private Bundle addLocalizedStringForKey(String key, Bundle localizedBundle) {
        if (bundle.getString(key) != null) {
            localizedBundle.putString(key, activity.getLocalizationUtilities().translate(bundle.getString(key)));
        }
        return localizedBundle;
    }
}
