package de.renew.formalism;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;

import org.junit.jupiter.api.Test;

import de.renew.formalism.java.ConstructorSuggestion;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class ConstructorSuggestionTest {
    @Test
    public void testConstructorSuggestion() throws Exception {
        //given
        final String typeName = "ExampleType";
        final Class<?>[] parameterTypes = { String.class, int.class };
        final Constructor<?> constructor = TestClass.class.getDeclaredConstructor(parameterTypes);

        //when
        ConstructorSuggestion testConstructorSuggestion =
            new TestableConstructorSuggestion(typeName, constructor);

        //then
        assertEquals(typeName, testConstructorSuggestion.getTypeName());
        assertEquals(typeName, testConstructorSuggestion.getName());
        assertEquals(constructor, testConstructorSuggestion.getConstructor());
    }

    @Test
    public void testToString() throws NoSuchMethodException {
        //given
        final String typeName = "ExampleType";
        final Class<?>[] parameterTypes = { String.class, int.class };
        final Constructor<?> constructor = TestClass.class.getDeclaredConstructor(parameterTypes);
        final ConstructorSuggestion testConstructorSuggestion =
            new TestableConstructorSuggestion(typeName, constructor);
        final String expectedString = "<html>" + "ExampleType(String, int)" + " <font color=gray>-"
            + " TestClass" + "</font></html>";
        //when
        final String resultString = testConstructorSuggestion.toString();

        //then
        assertEquals(expectedString, resultString);
    }

    @Test
    public void testSuggest() {
        //given
        final Collection<String> expectedCollection = new ArrayList<>();
        expectedCollection
            .add("<html>" + "Net()" + " <font color=gray>- " + "Net" + "</font></html>");
        expectedCollection
            .add("<html>" + "Net(String)" + " <font color=gray>- " + "Net" + "</font></html>");


        //when
        final Collection<ConstructorSuggestion> actualCollection =
            ConstructorSuggestion.suggest(de.renew.net.Net.class);

        //then
        assertThat(actualCollection.stream().map(Object::toString).toArray())
            .containsExactlyInAnyOrder(expectedCollection.toArray());
    }

    //Subclass, exposing the protected constructor
    private static class TestableConstructorSuggestion extends ConstructorSuggestion {
        public TestableConstructorSuggestion(String typeName, Constructor<?> constructor) {
            super(typeName, constructor);
        }
    }

    private static class TestClass {
        protected TestClass(String str, int num) {

        }
    }
}
