package com.atlassian.stash.internal.web.soy.functions;

import com.atlassian.bitbucket.auth.AuthenticationContext;
import com.atlassian.plugin.web.api.DynamicWebInterfaceManager;
import com.atlassian.plugin.web.descriptors.WebItemModuleDescriptor;
import com.atlassian.plugin.web.descriptors.WebPanelModuleDescriptor;
import com.atlassian.plugin.web.model.WebPanel;
import com.atlassian.sal.api.web.context.HttpContext;
import com.atlassian.soy.renderer.SanitizedString;
import com.atlassian.stash.internal.web.fragments.WebFragmentSupport;
import com.atlassian.stash.internal.web.fragments.WebPanelData;
import com.google.common.collect.ImmutableMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class WebPanelFunctionTest {

    private static final List<WebItemModuleDescriptor> EMPTY_LIST = Collections.emptyList();
    
    private static final String EMPTY_LOCATION = "empty.section";
    private static final String POPULATED_LOCATION = "populated.section";
    private static final String PLUGIN_KEY = "com.example.plugin";
    private static final String MODULE_KEY = "module-key";
    private static final String COMPLETE_KEY = PLUGIN_KEY + ":" + MODULE_KEY;
    private static final String HTML = "<div></div>";
    private static final int WEIGHT = 42;

    @Mock
    private DynamicWebInterfaceManager webInterfaceManager;

    @Mock
    private AuthenticationContext authenticationContext;

    @Mock
    private HttpContext httpContext;

    @Mock
    private HttpServletRequest request;
    
    private WebPanelFunction webPanelFunction;

    @Before
    public void setUp() throws Exception {
        WebPanel emptyPanel = mock(WebPanel.class);
        when(emptyPanel.getHtml(anyMap())).thenReturn("");

        WebPanelModuleDescriptor webPanelWithNullAccessors = mock(WebPanelModuleDescriptor.class);
        when(webPanelWithNullAccessors.getModule()).thenReturn(emptyPanel);

        WebPanel divPanel = mock(WebPanel.class);
        when(divPanel.getHtml(anyMap())).thenReturn(HTML);

        WebPanelModuleDescriptor webPanelWithNonnullAccessors = mock(WebPanelModuleDescriptor.class);
        when(webPanelWithNonnullAccessors.getLocation()).thenReturn(POPULATED_LOCATION);
        when(webPanelWithNonnullAccessors.getCompleteKey()).thenReturn(COMPLETE_KEY);
        when(webPanelWithNonnullAccessors.getWeight()).thenReturn(WEIGHT);
        when(webPanelWithNonnullAccessors.getModule()).thenReturn(divPanel);

        when(webInterfaceManager.getDisplayableWebPanelDescriptors(eq(EMPTY_LOCATION), anyMap()))
                .thenReturn(Collections.emptyList());
        when(webInterfaceManager.getDisplayableWebPanelDescriptors(eq(POPULATED_LOCATION), anyMap()))
                .thenReturn(Arrays.asList(webPanelWithNullAccessors, webPanelWithNonnullAccessors));

        doReturn(request).when(httpContext).getRequest();
        webPanelFunction = new WebPanelFunction(new WebFragmentSupport(webInterfaceManager, authenticationContext, httpContext));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testApplyWithTooFewArguments() throws Exception {
        webPanelFunction.apply();
    }

    @Test(expected = IllegalArgumentException.class)
    public void testApplyWithTooManyArguments() throws Exception {
        webPanelFunction.apply(null, null, null, null);
    }

    @Test
    public void testApplyOnEmptyLocation() throws Exception {
        final List<SanitizedString> result = webPanelFunction.apply(EMPTY_LOCATION);

        verify(webInterfaceManager, times(1)).getDisplayableWebPanelDescriptors(eq(EMPTY_LOCATION), anyMap());
        assertNotNull("result is not null", result);
        assertEquals("result is empty", result.size(), EMPTY_LIST.size());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testWebSectionDataWithInvalidCompleteKey() {
        new WebPanelData("key-without-colon", "location", HTML, 1, ImmutableMap.of());
    }

    @Test
    public void testApplyOnNonEmptyLocation() throws Exception {
        List<SanitizedString> result = webPanelFunction.apply(POPULATED_LOCATION);

        verify(webInterfaceManager, times(1)).getDisplayableWebPanelDescriptors(eq(POPULATED_LOCATION), anyMap());
        assertNotNull("result is not null", result);
        assertEquals("result has two item", result.size(), 2);

        SanitizedString html = result.get(1);
        assertEquals(HTML, html.getValue());
    }

}
