package com.atlassian.stash.internal.rest.fragment;

import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.rest.fragment.RestFragments;
import com.atlassian.bitbucket.rest.fragment.RestFragmentContext;
import com.atlassian.plugin.PluginAccessor;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class PluginRestFragmentsFactoryTest {

    @InjectMocks
    private PluginRestFragmentsFactory factory;
    @Mock
    private PluginAccessor pluginAccessor;

    @Test
    public void testExistsForKey() throws Exception {
        RestFragmentModuleDescriptor descriptor = mock(RestFragmentModuleDescriptor.class);
        when(descriptor.getLocation()).thenReturn("restKey");

        when(pluginAccessor.getEnabledModuleDescriptorsByClass(RestFragmentModuleDescriptor.class))
                .thenReturn(Collections.singletonList(descriptor));

        assertTrue(factory.existsForKey("restKey"));
    }

    @Test
    public void testExistsForKeyForNonExistentKey() throws Exception {
        RestFragmentModuleDescriptor descriptor = mock(RestFragmentModuleDescriptor.class);
        when(descriptor.getLocation()).thenReturn("restKey");

        when(pluginAccessor.getEnabledModuleDescriptorsByClass(RestFragmentModuleDescriptor.class))
                .thenReturn(Collections.singletonList(descriptor));

        assertFalse(factory.existsForKey("anotherRestKey"));
    }

    @Test
    public void testForKey() throws Exception {
        RestFragmentModuleDescriptor descriptor1 = mock(RestFragmentModuleDescriptor.class, Mockito.RETURNS_DEEP_STUBS);
        when(descriptor1.getLocation()).thenReturn("restKey");

        RestFragmentModuleDescriptor descriptor2 = mock(RestFragmentModuleDescriptor.class, Mockito.RETURNS_DEEP_STUBS);
        when(descriptor2.getLocation()).thenReturn("restKey");

        Repository repository = mock(Repository.class);

        when(descriptor1.compareTo(same(descriptor2))).thenReturn(-1);
        when(descriptor2.compareTo(same(descriptor1))).thenReturn(1);

        when(pluginAccessor.getEnabledModuleDescriptorsByClass(RestFragmentModuleDescriptor.class))
                .thenReturn(Arrays.asList(descriptor2, descriptor1)); //Reverse order to verify sorting is applied

        RestFragmentContext fragmentContext = mock(RestFragmentContext.class);
        RestFragments fragments = factory.forKey("restKey", ImmutableMap.<String, Object>of("repository", repository));
        fragments.execute(fragmentContext);

        Map<String, Object> requestContext = ImmutableMap.of("repository", repository);
        InOrder ordered = inOrder(descriptor1.getModule(), descriptor2.getModule());
        ordered.verify(descriptor1.getModule()).execute(fragmentContext, requestContext);
        ordered.verify(descriptor2.getModule()).execute(fragmentContext, requestContext);
    }
}