package com.mobify.astro.plugins;

import android.support.design.widget.TabLayout;
import android.widget.RelativeLayout;

import com.mobify.astro.ActivityTestBase;
import com.mobify.astro.PluginResolver;
import com.mobify.astro.R;
import com.mobify.astro.messaging.EventManager;
import com.mobify.astro.messaging.MessageSender;

import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

public class TabBarPluginTest extends ActivityTestBase {
    final static String IMAGE_URL = "file:///test-image.png";
    final static String ITEM_TITLE = "Home";
    final static String ITEM_ID = "home";
    final static String SELECTED_COLOR = "#00AAAAAA";
    final static String UNSELECTED_COLOR = "#00BBBBBB";

    @Rule
    public ExpectedException exception = ExpectedException.none();

    private TabBarPlugin tabBarPlugin;

    @Before
    public void setup() throws Throwable {
        PluginResolver mockPluginResolver = mock(PluginResolver.class);
        EventManager mockEventManager = mock(EventManager.class);
        MessageSender messageSender = new MessageSender(mockEventManager);
        tabBarPlugin = new TabBarPlugin(getActivity(), mockPluginResolver, mockEventManager, messageSender);
    }

    private JSONObject buildItem(String imageUrl, String selectedImageUrl, String title, String itemId) throws Exception{
        JSONObject item = new JSONObject();

        if (imageUrl != null) {
            item.put("imageUrl", imageUrl);
        }

        if (selectedImageUrl != null) {
            item.put("selectedImageUrl", selectedImageUrl);
        }

        if (title != null) {
            item.put("title", title);
        }

        if (itemId != null) {
            item.put("id", itemId);
        }

        return item;
    }

    private RelativeLayout getTabBarView() {
        return (RelativeLayout) tabBarPlugin.getView();
    }

    private TabLayout getTabBarLayout() {
        RelativeLayout layout = getTabBarView();
        return (TabLayout) layout.findViewById(R.id.tabLayout);
    }

    private TabBarPlugin.TabData getTabData(TabLayout tabLayout, int index) {
        return (TabBarPlugin.TabData) tabLayout.getTabAt(index).getTag();
    }

    @Test
    public void testGetView() { assertNotNull(getTabBarView()); }

    @Test
    public void testSetItems() throws Exception{
        JSONArray items = new JSONArray();
        items.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        tabBarPlugin.setItems(items);

        TabLayout tabLayout = getTabBarLayout();
        assertEquals(items.length(), tabLayout.getTabCount());

        TabBarPlugin.TabData tab = getTabData(tabLayout, 0);
        assertEquals(ITEM_ID, tab.id);
        assertEquals(ITEM_TITLE, tab.title);
        assertNotNull(tab.image);
        assertNotNull(tab.selectedImage);
    }

    @Test
    public void testSetItemsWithEmptyList() throws Exception{
        JSONArray items = new JSONArray();
        items.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        tabBarPlugin.setItems(items);

        TabLayout tabLayout = getTabBarLayout();
        assertEquals(items.length(), tabLayout.getTabCount());

        tabBarPlugin.setItems(new JSONArray());

        assertEquals(0, tabLayout.getTabCount());
    }

    @Test
    public void testSetItemsWithEmptyValue() throws Exception{
        JSONArray items = new JSONArray();
        items.put(buildItem("", "", "", ""));

        exception.expect(RuntimeException.class);
        tabBarPlugin.setItems(items);
    }

    @Test
    public void testSetItemsWithPartialFilledValues() throws Exception{
        JSONArray items = new JSONArray();
        items.put(buildItem(IMAGE_URL, IMAGE_URL, "", ITEM_ID));

        exception.expect(Exception.class);
        tabBarPlugin.setItems(items);
    }

    @Test
    public void testSetItemsRestoresSelectedItem() throws Exception{
        JSONArray firstItemSet = new JSONArray();
        firstItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        tabBarPlugin.setItems(firstItemSet);

        TabLayout tabLayout = getTabBarLayout();
        assertEquals(firstItemSet.length(), tabLayout.getTabCount());

        TabBarPlugin.TabData tab = getTabData(tabLayout, tabLayout.getSelectedTabPosition());
        assertEquals(ITEM_TITLE, tab.title);

        JSONArray secondItemSet = new JSONArray();
        secondItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, "Search", "search"));
        secondItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));
        secondItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, "Account", "account"));

        tabBarPlugin.setItems(secondItemSet);
        assertEquals(secondItemSet.length(), tabLayout.getTabCount());

        tab = getTabData(tabLayout, tabLayout.getSelectedTabPosition());
        assertEquals(ITEM_TITLE, tab.title);
    }

    @Test
    public void testSubscribedToLocaleUpdates() {
        verify(tabBarPlugin.localizationUtilities).addLocaleChangedListener(tabBarPlugin);
    }

    @Test
    public void setItemsNoColorSetNoTintDrawableCalled() throws Exception {
        JSONArray firstItemSet = new JSONArray();
        firstItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        TabBarPlugin spiedPlugin = spy(tabBarPlugin);

        spiedPlugin.setItems(firstItemSet);

        verify(spiedPlugin, never()).createTintedDrawable(any(String.class), anyInt());
    }

    @Test
    public void setItemsSelectedColorSetTintDrawableCalled() throws Exception {
        JSONArray firstItemSet = new JSONArray();
        firstItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        TabBarPlugin spiedPlugin = spy(tabBarPlugin);
        spiedPlugin.setColor(SELECTED_COLOR, null);

        spiedPlugin.setItems(firstItemSet);

        verify(spiedPlugin, times(2)).createTintedDrawable(any(String.class), anyInt());
    }

    @Test
    public void setItemsSelectedAndUnselectedColorSetTintDrawableCalled() throws Exception {
        JSONArray firstItemSet = new JSONArray();
        firstItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        TabBarPlugin spiedPlugin = spy(tabBarPlugin);
        spiedPlugin.setColor(SELECTED_COLOR, UNSELECTED_COLOR);

        spiedPlugin.setItems(firstItemSet);

        verify(spiedPlugin, times(2)).createTintedDrawable(any(String.class), anyInt());
    }

    @Test
    public void setColorNoItemsSetNoTintDrawableCalled() throws Exception {
        TabBarPlugin spiedPlugin = spy(tabBarPlugin);

        spiedPlugin.setColor(SELECTED_COLOR, UNSELECTED_COLOR);

        verify(spiedPlugin, never()).createTintedDrawable(any(String.class), anyInt());
    }

    @Test
    public void setColorSelectedColorOneItemSetTintDrawableCalledTwice() throws Exception {
        JSONArray firstItemSet = new JSONArray();
        firstItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        TabBarPlugin spiedPlugin = spy(tabBarPlugin);
        spiedPlugin.setItems(firstItemSet);

        spiedPlugin.setColor(SELECTED_COLOR, null);

        verify(spiedPlugin, times(2)).createTintedDrawable(any(String.class), anyInt());
    }

    @Test
    public void setColorSelectedAndUnselectedColorsOneItemSetTintDrawableCalledTwice() throws Exception {
        JSONArray firstItemSet = new JSONArray();
        firstItemSet.put(buildItem(IMAGE_URL, IMAGE_URL, ITEM_TITLE, ITEM_ID));

        TabBarPlugin spiedPlugin = spy(tabBarPlugin);
        spiedPlugin.setItems(firstItemSet);

        spiedPlugin.setColor(SELECTED_COLOR, UNSELECTED_COLOR);

        verify(spiedPlugin, times(2)).createTintedDrawable(any(String.class), anyInt());
    }
}
