package com.mobify.astro.plugins;

import android.view.View;

import com.mobify.astro.ActivityTestBase;
import com.mobify.astro.AstroPlugin;
import com.mobify.astro.PluginResolver;
import com.mobify.astro.TestPlugin;
import com.mobify.astro.messaging.EventManager;
import com.mobify.astro.messaging.MessageSender;
import com.mobify.astro.plugins.layouts.AnimatableSectionedContainerView;

import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class AnchoredLayoutPluginTest extends ActivityTestBase {
    private AnchoredLayoutPlugin layoutPlugin;
    private AstroPlugin plugin;
    PluginResolver mockPluginResolver;

    @Before
    public void setUp() throws Exception {
        mockPluginResolver = mock(PluginResolver.class);
        EventManager eventManager = new EventManager();
        MessageSender messageSender = new MessageSender(eventManager);
        plugin = new TestPlugin(getActivity(), mockPluginResolver, eventManager, messageSender);
        when(mockPluginResolver.instanceForAddress(plugin.getInstanceAddress())).thenReturn(plugin);
        layoutPlugin = new AnchoredLayoutPlugin(getActivity(), mockPluginResolver, eventManager, messageSender);
    }

    @Test
    public void testInitialLayout() throws Exception {
        assertNotNull(layoutPlugin.containerView);
        assertEquals(1, layoutPlugin.containerView.getChildCount());
    }

    @Test
    public void testSetAndClearContentView() throws Exception {
        layoutPlugin.setContentView(plugin.getInstanceAddress());
        assertEquals(layoutPlugin.containerView.getChildAt(0), plugin.getView());
        layoutPlugin.clearContentView();
        assertNull(layoutPlugin.containerView.getChildAt(0));
    }

    @Test
    public void testAddAndClearTopView() throws Exception {
        layoutPlugin.addTopView(plugin.getInstanceAddress(), new JSONObject("{height: 40}"));
        assertEquals(layoutPlugin.containerView.getChildAt(0), plugin.getView());
        layoutPlugin.clearTopViews(null);

        // Child at 0 will now be the middle view
        assertNotEquals(layoutPlugin.containerView.getChildAt(0), plugin.getView());
    }

    @Test
    public void testAddAndClearBottomView() throws Exception {
        layoutPlugin.addBottomView(plugin.getInstanceAddress(), new JSONObject("{height: 40}"));
        assertEquals(layoutPlugin.containerView.getChildAt(1), plugin.getView());
        layoutPlugin.clearBottomViews(null);
        assertNull(layoutPlugin.containerView.getChildAt(1));
    }

    @Test
    public void testShowView() throws Exception {
        layoutPlugin.addTopView(plugin.getInstanceAddress(), new JSONObject("{height: 40}"));
        plugin.getView().setVisibility(View.GONE);

        layoutPlugin.showView(plugin.getInstanceAddress(), new JSONObject());
        assertEquals(View.VISIBLE, plugin.getView().getVisibility());
    }

    @Test
    public void testShowViewNullOptions() throws Exception {
        layoutPlugin.addTopView(plugin.getInstanceAddress(), new JSONObject("{height: 40}"));
        plugin.getView().setVisibility(View.GONE);

        layoutPlugin.showView(plugin.getInstanceAddress(), null);
        assertEquals(View.VISIBLE, plugin.getView().getVisibility());
    }

    @Test
    public void testShowViewNotInAnchoredLayoutShouldNotShow() throws Exception {
        plugin.getView().setVisibility(View.GONE);

        layoutPlugin.showView(plugin.getInstanceAddress(), null);
        assertEquals(View.GONE, plugin.getView().getVisibility());
    }

    @Test
    public void testHideView() throws Exception {
        layoutPlugin.addTopView(plugin.getInstanceAddress(), new JSONObject("{height: 40}"));
        assertEquals(View.VISIBLE, plugin.getView().getVisibility());

        layoutPlugin.hideView(plugin.getInstanceAddress(), new JSONObject());
        assertEquals(View.GONE, plugin.getView().getVisibility());
    }

    @Test
    public void testShowTopViews() throws Exception {
        AnimatableSectionedContainerView mockedContainerView = mock(AnimatableSectionedContainerView.class);
        layoutPlugin.containerView = mockedContainerView;

        layoutPlugin.showTopViews(new JSONObject());

        verify(mockedContainerView, times(1)).setVisibilityTopViews(View.VISIBLE);
    }

    @Test
    public void testHideTopViews() throws Exception {
        AnimatableSectionedContainerView mockedContainerView = mock(AnimatableSectionedContainerView.class);
        layoutPlugin.containerView = mockedContainerView;

        layoutPlugin.hideTopViews(new JSONObject());

        verify(mockedContainerView, times(1)).setVisibilityTopViews(View.GONE);
    }

    @Test
    public void testShowBottomViews() throws Exception {
        AnimatableSectionedContainerView mockedContainerView = mock(AnimatableSectionedContainerView.class);
        layoutPlugin.containerView = mockedContainerView;

        layoutPlugin.showBottomViews(new JSONObject());

        verify(mockedContainerView, times(1)).setVisibilityBottomViews(View.VISIBLE);
    }

    @Test
    public void testHideBottomViews() throws Exception {
        AnimatableSectionedContainerView mockedContainerView = mock(AnimatableSectionedContainerView.class);
        layoutPlugin.containerView = mockedContainerView;

        layoutPlugin.hideBottomViews(null);

        verify(mockedContainerView, times(1)).setVisibilityBottomViews(View.GONE);
    }

    @Test
    public void testToggleView() throws Exception {
        String pluginAddress = plugin.getInstanceAddress();
        JSONObject options = new JSONObject();
        layoutPlugin.addTopView(pluginAddress, options);
        layoutPlugin.toggleView(pluginAddress, options);

        assertEquals(View.GONE, plugin.getView().getVisibility());

        layoutPlugin.toggleView(pluginAddress, options);
        assertEquals(View.VISIBLE, plugin.getView().getVisibility());
    }
}
