package com.mobify.astro.plugins;

import android.os.Bundle;

import com.mobify.astro.ActivityTestBase;
import com.mobify.astro.AstroActivity;
import com.mobify.astro.PluginResolver;
import com.mobify.astro.dialogs.DialogManager;
import com.mobify.astro.messaging.EventManager;
import com.mobify.astro.messaging.MessageSender;
import com.mobify.astro.messaging.RpcResponse;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class ListSelectPluginTest extends ActivityTestBase {

    private ListSelectPlugin listSelectPlugin;
    private DialogManager mockDialogManager;
    private RpcResponse response;

    @Before
    public void setup() {
        PluginResolver mockPluginResolver = mock(PluginResolver.class);
        EventManager mockEventManager = mock(EventManager.class);
        MessageSender mockMessageSender = mock(MessageSender.class);
        listSelectPlugin = new ListSelectPlugin(getActivity(), mockPluginResolver, mockEventManager, mockMessageSender);

        mockDialogManager = mock(DialogManager.class);
        listSelectPlugin.dialogManager = mockDialogManager;
    }

    @Test
    public void testSetTitle() {
        final String title = "title";
        listSelectPlugin.setTitle(title);
        assertEquals(title, listSelectPlugin.bundle.getString(ListSelectPlugin.KEY_TITLE));
    }

    @Test
    public void testParsingValidItem() throws Exception {
        final String id = "ID";
        final String label = "THIS IS THE LABEL";

        final JSONObject item = new JSONObject();
        item.put("label", label);
        item.put("id", id);

        ListSelectPlugin.ListItem parsedItem = listSelectPlugin.parseItem(item);
        assertEquals(id, parsedItem.id);
        assertEquals(label, parsedItem.label);
    }

    @Test
    public void testParsingInvalidItemShouldThrowException() throws Exception {
        final JSONObject invalidItem = new JSONObject();

        invalidItem.put("idadfasdf", "asdfasf");

        try {
            listSelectPlugin.parseItem(invalidItem);
            fail("Parsing an invalid list item should fail.");
        } catch (ListSelectPlugin.ListSelectPluginException e) {
            assertNotNull(e);
        }
    }

    @Test
    public void testSettingCancellable() {
        listSelectPlugin.setCancelable(false);
        assertFalse(listSelectPlugin.cancelable);

        listSelectPlugin.setCancelable(true);
        assertTrue(listSelectPlugin.cancelable);
    }

    public JSONArray createList(int size) throws JSONException {
        JSONArray list = new JSONArray();
        for (int i = 0; i < size; i++) {
            JSONObject item = new JSONObject();
            item.put("id", "id-" + i);
            item.put("label", "LABEL-" + i);
            list.put(item);
        }
        return list;
    }

    @Test
    public void testSetList() throws Exception {
        final JSONArray list = createList(5);

        assertEquals(0, listSelectPlugin.list.size());
        listSelectPlugin.setList(list);
        assertEquals(list.length(), listSelectPlugin.list.size());

        for (int i =0 ; i < list.length(); i++) {
            JSONObject expectedItem = (JSONObject) list.get(i);
            ListSelectPlugin.ListItem actualItem = listSelectPlugin.list.get(i);

            assertEquals(expectedItem.get("id"), actualItem.id);
            assertEquals(expectedItem.get("label"), actualItem.label);
        }
    }

    @Test
    public void testOverridingList() throws Exception {
        assertEquals(0, listSelectPlugin.list.size());

        JSONArray list = createList(2);
        listSelectPlugin.setList(list);
        assertEquals(list.length(), listSelectPlugin.list.size());

        list = createList(10);
        listSelectPlugin.setList(list);
        assertEquals(list.length(), listSelectPlugin.list.size());

        listSelectPlugin.setList(new JSONArray());
        assertEquals(0, listSelectPlugin.list.size());
    }

    @Test
    public void testShowingListWithNoItemsShouldThrownException() throws Exception {
        try {
            listSelectPlugin.show(response, null);
            fail("Showing a List Select with no items should throw an exception");
        } catch (ListSelectPlugin.ListSelectPluginException e) {
            assertNotNull(e);
        }

    }

    @Test
    public void testShowingDialog() throws Exception {
        JSONArray list = createList(4);
        listSelectPlugin.setList(list);
        listSelectPlugin.show(response, null);

        ArgumentCaptor<Bundle> argumentCaptor = ArgumentCaptor.forClass(Bundle.class);
        verify(mockDialogManager).showListSelect(argumentCaptor.capture(), eq(listSelectPlugin.list), any(AstroActivity.class), eq(response), eq(listSelectPlugin.REQUEST_CODE));
        Bundle actualBundle = argumentCaptor.getValue();
        Bundle expectedBundle = listSelectPlugin.getLocalizedBundle();
        assertEquals(expectedBundle.getString(ListSelectPlugin.KEY_CANCEL_BUTTON), actualBundle.getString(ListSelectPlugin.KEY_CANCEL_BUTTON));
        assertEquals(expectedBundle.getBoolean(ListSelectPlugin.KEY_CANCELABLE), actualBundle.getBoolean(ListSelectPlugin.KEY_CANCELABLE));
    }
}
