package com.atlassian.stash.internal.user;

import com.atlassian.bitbucket.permission.*;
import com.atlassian.bitbucket.user.*;
import com.google.common.collect.Iterables;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ExternalUserPermissionGraphFactoryTest {
    @InjectMocks
    private ExternalUserPermissionGraphFactory factory;
    @Mock
    private EffectivePermissionsProviderTracker permsProviderTracker;
    @Mock
    private EffectivePermissionsProvider provider;

    @Before
    public void seUpProvider() throws Exception {
        when(permsProviderTracker.getProviders()).thenReturn(Collections.singleton(provider));
        when(provider.getPermissions(any(ApplicationUser.class))).thenReturn(Collections.<EffectivePermission>emptyList());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testErrorIfInternalUser() throws Exception {
        ApplicationUser user = UserTestUtils.createMockNormalUser(InternalApplicationUser.class);
        factory.createGraph(user);
    }

    @Test
    public void testNormalUserWithNoEffectivePermissions() throws Exception {
        ApplicationUser user = UserTestUtils.createMockNormalUser(ApplicationUser.class);
        assertTrue(Iterables.isEmpty(factory.createGraph(user)));
    }

    @Test
    public void testNormalUserWithEffectivePermissions() throws Exception {
        ApplicationUser user = UserTestUtils.createMockNormalUser(ApplicationUser.class);
        when(provider.getPermissions(user)).thenReturn(Collections.<EffectivePermission>singleton(
                new SimpleEffectiveGlobalPermission(Permission.SYS_ADMIN)
        ));
        IterablePermissionGraph graph = factory.createGraph(user);
        assertEquals(1, Iterables.size(graph));
        assertTrue(Iterables.contains(graph, new SimpleEffectiveGlobalPermission(Permission.SYS_ADMIN)));
    }

    @Test
    public void testServiceUsersAreLicensed() throws Exception {
        ServiceUser user = UserTestUtils.createMockServiceUser(ServiceUser.class);
        IterablePermissionGraph graph = factory.createGraph(user);
        assertEquals(1, Iterables.size(graph));
        assertTrue(Iterables.contains(graph, new SimpleEffectiveGlobalPermission(Permission.LICENSED_USER)));
    }

    @Test
    public void testServiceUserWithEffectivePermissions() throws Exception {
        ServiceUser user = UserTestUtils.createMockServiceUser(ServiceUser.class);
        when(provider.getPermissions(user)).thenReturn(Arrays.<EffectivePermission>asList(
                new SimpleEffectiveGlobalPermission(Permission.LICENSED_USER),
                new SimpleEffectiveProjectPermission(1, Permission.PROJECT_READ),
                new SimpleEffectiveRepositoryPermission(1, Permission.REPO_READ)
        ));
        IterablePermissionGraph graph = factory.createGraph(user);
        assertEquals(3, Iterables.size(graph));
        assertTrue(Iterables.contains(graph, new SimpleEffectiveProjectPermission(1, Permission.PROJECT_READ)));
        assertTrue(Iterables.contains(graph, new SimpleEffectiveRepositoryPermission(1, Permission.REPO_READ)));
        assertTrue(Iterables.contains(graph, new SimpleEffectiveGlobalPermission(Permission.LICENSED_USER)));
    }
}
