package com.atlassian.stash.internal.avatar;

import com.atlassian.bitbucket.avatar.AvatarSupplier;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.junit.Assert.*;

//Note: This test is in service-impl instead of service-api so it will have access to the resources for default avatars
public class AvatarTypeTest {

    private static final Pattern PATTERN_PROJECT_PATH = Pattern.compile("avatars/project/([^/]+)/([\\d]+)\\.svg");
    private static final Pattern PATTERN_USER_PATH = Pattern.compile("avatars/user/([\\d]+)\\.png");

    @Test
    public void testLoadDefaultForProject() throws Exception {
        String lastColour = null;
        for (int size : AvatarType.DEFAULT_SIZES) {
            AvatarSupplier supplier = AvatarType.PROJECT.loadDefault("1", size);
            assertNotNull("Loading a default project avatar should never return null", supplier);
            assertEquals("Project avatar has wrong content type",
                    AvatarType.PROJECT.getContentType(), supplier.getContentType());

            ClassPathResource resource = ((ResourceAvatarSupplier) supplier).getResource();
            Matcher matcher = PATTERN_PROJECT_PATH.matcher(resource.getPath());
            assertTrue("The avatar's name does not match the expected pattern", matcher.matches());
            if (lastColour == null) {
                //Extract the colour of the first avatar returned and store it. This will be used to validate that,
                //given the same ID, the colour is stable across requests
                lastColour = matcher.group(1);
            } else {
                String actual = matcher.group(1);

                assertTrue("Colour is not stable across requests", lastColour.equals(actual));
            }
            assertEquals("The avatar size is not what was requested", size, Integer.parseInt(matcher.group(2)));

            try (InputStream stream = supplier.open()) {
                assertNotNull("The avatar did not provide an InputStream", stream);
            }
        }
    }

    @Test
    public void testLoadDefaultForUser() throws Exception {
        for (int size : AvatarType.DEFAULT_SIZES) {
            AvatarSupplier supplier = AvatarType.USER.loadDefault("1", size);
            assertNotNull("Loading a default user avatar should never return null", supplier);
            assertEquals("User avatar has wrong content type",
                    AvatarType.USER.getContentType(), supplier.getContentType());

            ClassPathResource resource = ((ResourceAvatarSupplier) supplier).getResource();
            Matcher matcher = PATTERN_USER_PATH.matcher(resource.getPath());
            assertTrue("The user avatar's name does not match the expected pattern", matcher.matches());
            assertEquals("The user avatar size is not what was requested", size, Integer.parseInt(matcher.group(1)));

            try (InputStream stream = supplier.open()) {
                assertNotNull("The user avatar did not provide an InputStream", stream);
            }
        }
    }

    @Test(expected = IllegalArgumentException.class)
    public void testLoadDefaultWithInvalidSize() {
        AvatarType.PROJECT.loadDefault("1", 99);
    }

    @Test
    public void testLoadFixedDefault() throws Exception {
        for (AvatarType type : AvatarType.values()) {
            AvatarSupplier supplier = type.loadFixedDefault(64);
            assertNotNull(type.name() + " has no fixed default avatar", supplier);
            assertEquals("The fixed default avatar for " + type.name() + " has the wrong content type",
                    type.getContentType(), supplier.getContentType());

            try (InputStream stream = supplier.open()) {
                assertNotNull("The fixed default avatar for " + type.name() + " did not provide an InputStream", stream);
            }
        }
    }
}
