package com.atlassian.stash.internal.applinks.spi;

import com.atlassian.applinks.api.application.stash.StashProjectEntityType;
import com.atlassian.applinks.host.spi.EntityReference;
import com.atlassian.applinks.spi.util.TypeAccessor;
import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.project.ProjectService;
import com.atlassian.bitbucket.server.ApplicationPropertiesService;
import com.atlassian.bitbucket.user.DummySecurityService;
import com.atlassian.bitbucket.permission.PermissionService;
import com.atlassian.bitbucket.user.SecurityService;
import com.atlassian.bitbucket.util.PageRequest;
import com.atlassian.bitbucket.util.PageUtils;
import com.google.common.collect.Iterables;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

import java.util.Collections;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.mockito.Matchers.notNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class StashHostApplicationTest {

    @Mock
    private ApplicationPropertiesService applicationPropertiesService;
    @Mock
    private PermissionService permissionService;
    @Mock
    private ProjectService projectService;
    private SecurityService securityService = new DummySecurityService();
    @InjectMocks
    private StashHostApplication stashHostApplication;
    @Mock
    private TypeAccessor typeAccessor;

    @Test
    public void testGetName() throws Exception {
        when(applicationPropertiesService.getDisplayName()).thenReturn("stash-test");
        assertEquals("stash-test", stashHostApplication.getName());
    }

    @Test
    public void testGetLocalEntities() throws Exception {
        getLocalEntities(1);
        getLocalEntities(135);
    }

    private void getLocalEntities(final int size) {
        final Project project = mock(Project.class);
        when(project.getKey()).thenReturn("prj-key");
        when(project.getName()).thenReturn("prj-name");

        when(projectService.findAll(notNull(PageRequest.class))).thenAnswer(new Answer<Object>() {
            public Object answer(InvocationOnMock invocation) throws Throwable {
                PageRequest request = (PageRequest) invocation.getArguments()[0];
                return PageUtils.createPage(Collections.nCopies(size - request.getStart(), project), request);
            }
        });

        StashProjectEntityType type = mock(StashProjectEntityType.class);
        when(typeAccessor.getEntityType(StashProjectEntityType.class)).thenReturn(type);

        Iterable<EntityReference> entities = stashHostApplication.getLocalEntities();
        assertEquals(size, Iterables.size(entities));
        EntityReference entity = Iterables.get(entities, 0);
        assertEquals("prj-key", entity.getKey());
        assertEquals("prj-name", entity.getName());
        assertSame(type, entity.getType());
    }
}
