package com.atlassian.stash.internal.user;

import com.atlassian.bitbucket.permission.Permission;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class DefaultPermissionGraphEncoderTest {

    private final DefaultPermissionGraph.Encoding encoding = new DefaultPermissionGraph.Encoding();

    @Test
    public void testPermissionsFitInEncoding() {
        // the encoding allocates 3 bytes for the permission encoding. In the current encoding scheme that means that
        // the highest permission id that can be encoded = 23
        for (Permission permission : Permission.values()) {
            assertTrue("permission.id must be in the [0, 24) range. Values outside this range cannot be encoded",
                    permission.getId() >= 0 && permission.getId() < 24);
        }

    }

    @Test
    public void testGlobalPermission() {
        verifyEncodeDecode(Permission.SYS_ADMIN, null);
        verifyEncodeDecode(Permission.ADMIN, null);
        verifyEncodeDecode(Permission.PROJECT_CREATE, null);
        verifyEncodeDecode(Permission.LICENSED_USER, null);
    }

    @Test
    public void testProjectPermission() {
        verifyEncodeDecode(Permission.PROJECT_ADMIN, 1);
        verifyEncodeDecode(Permission.PROJECT_WRITE, 9);
        verifyEncodeDecode(Permission.PROJECT_READ, 1088);
        verifyEncodeDecode(Permission.PROJECT_VIEW, 898989);
    }

    @Test
    public void testRepoPermission() {
        verifyEncodeDecode(Permission.REPO_ADMIN, Integer.MAX_VALUE);
        verifyEncodeDecode(Permission.REPO_READ, 1);
        verifyEncodeDecode(Permission.REPO_WRITE, 99);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testResourcePermissionNegativeId() {
        encoding.encode(Permission.REPO_READ, -1);
    }

    @Test
    public void testShouldOutputOnlyPermissionNameForGlobalPermissions() throws Exception {
        assertEquals("SYS_ADMIN", encoding.toString(encoding.encode(Permission.SYS_ADMIN, null)));
    }

    @Test
    public void testShouldOutputPermissionNameAndResourceIdForResourcePermissions() throws Exception {
        assertEquals("PROJECT_READ: 1234", encoding.toString(encoding.encode(Permission.PROJECT_READ, 1234)));
        assertEquals("REPO_ADMIN: 321", encoding.toString(encoding.encode(Permission.REPO_ADMIN, 321)));
    }

    private void verifyEncodeDecode(Permission permission, Integer resourceId) {
        long encoded = encoding.encode(permission, resourceId);

        assertEquals(permission, encoding.decodePermission(encoded));
        assertEquals(resourceId != null ? resourceId.intValue() : 0, encoding.decodeResourceId(encoded));
    }
}
