package io.dropwizard.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@SuppressWarnings("serial")
@RunWith(Parameterized.class)
public class GenericsTest {

    @Parameters(name = "Test {0}")
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
            {Object.class, Object.class, Object.class, Object.class, IllegalStateException.class, "Cannot figure out type parameterization for " + Object.class.getName() },
            {null, null, null, null, NullPointerException.class, null },
            {IntegerList.class, Integer.class, Number.class, Integer.class, null, null },
            {IntegerList.class, Integer.class, Integer.class, Integer.class, null, null },
            {NumberList.class, Number.class, Number.class, Number.class, null, null },
            {IntegerValueMap.class, Object.class, Number.class, Integer.class, null, null },
        });
    }

    private Class<?> klass;
    private Class<?> typeParameter;
    private Class<?> bound;
    private Class<?> boundTypeParameter;
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    public GenericsTest(Class<?> klass, Class<?> typeParameter, Class<?> bound, Class<?> boundTypeParameter, Class<? extends Exception> expectedException, String expectedMessage) {
        this.klass = klass;
        this.typeParameter = typeParameter;
        this.bound = bound;
        this.boundTypeParameter = boundTypeParameter;
        
        if (expectedException != null) {
            thrown.expect(expectedException);
            if (expectedMessage != null)
                thrown.expectMessage(expectedMessage);
        }
    }

    @Test
    public void testTypeParameter() {
        assertThat(Generics.getTypeParameter(klass)).isEqualTo(typeParameter);
    }
    
    @Test
    public void testBoundTypeParameter() {
        assertThat(Generics.getTypeParameter(klass, bound)).isEqualTo(boundTypeParameter);
    }
    
    public static class IntegerList extends ArrayList<Integer> { }
    public static class NumberList<V extends Number> extends ArrayList<V> { }
    public static class IntegerValueMap<K> extends HashMap<K, Integer> { }
}

@@ -485,16 +485,19 @@
 ricsTest
+%3CT%3E
  %7B%0A%0A    
@@ -1326,24 +1326,32 @@
 vate Class%3C?
+ super T
 %3E bound;%0A   
@@ -1530,24 +1530,32 @@
 ter, Class%3C?
+ super T
 %3E bound, Cla
@@ -1806,24 +1806,16 @@
 ameter;%0A
-        
 %0A       

Fix 'GenericsTest' to compile in IntelliJ (#2089) (#2095)