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.api.WebSection;
import com.atlassian.plugin.web.api.model.WebFragmentBuilder;
import com.atlassian.plugin.web.descriptors.WebItemModuleDescriptor;
import com.atlassian.sal.api.web.context.HttpContext;
import com.atlassian.stash.internal.web.fragments.WebFragmentSupport;
import com.atlassian.stash.internal.web.fragments.WebSectionData;
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 WebSectionFunctionTest {

    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 ID = "id";
    private static final String LABEL = "label";
    private static final int WEIGHT = 42;

    @Mock
    private DynamicWebInterfaceManager webInterfaceManager;

    @Mock
    private AuthenticationContext authenticationContext;

    @Mock
    private HttpContext httpContext;

    @Mock
    private HttpServletRequest request;
    
    private WebSectionFunction webSectionFunction;

    @Before
    public void setUp() throws Exception {
        WebSection webSectionWithNullAccessors = new WebFragmentBuilder(0)
                .webSection(POPULATED_LOCATION)
                .build();

        WebSection webSectionWithNonnullAccessors = new WebFragmentBuilder(COMPLETE_KEY, WEIGHT)
                .id(ID)
                .label(LABEL)
                .webSection(POPULATED_LOCATION)
                .build();

        when(webInterfaceManager.getDisplayableWebSections(eq(EMPTY_LOCATION), anyMap()))
                .thenReturn(Collections.emptyList());
        when(webInterfaceManager.getDisplayableWebSections(eq(POPULATED_LOCATION), anyMap()))
                .thenReturn(Arrays.asList(webSectionWithNullAccessors, webSectionWithNonnullAccessors));

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

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

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

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

        verify(webInterfaceManager, times(1)).getDisplayableWebSections(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 WebSectionData("key-without-colon", "id", "location", "label-text", 1, ImmutableMap.of());
    }

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

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

        WebSectionData section = result.get(1);
        assertEquals(LABEL, section.getLabelText());
        assertEquals(COMPLETE_KEY, section.getCompleteKey());
        assertEquals(PLUGIN_KEY, section.getPluginKey());
        assertEquals(MODULE_KEY, section.getModuleKey());
        assertEquals(MODULE_KEY, section.getKey());
        assertEquals(WEIGHT, section.getWeight());
    }

}
