package de.renew.netcomponents;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.storables.ontology.FigureEnumeration;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * This class is a test class for {@link Util}
 *
 * @author 0zander
 */
public class UtilTest {

    /**
     * Tests the method {@link Util#iterator2array(Iterator)}.
     * This tests for an array consisting of 0, 1 and 2 objects.
     *
     * @param objects an array of objects used for the conversion.
     */
    @ParameterizedTest
    @EmptySource
    @MethodSource("objectArrayProvider")
    public void testIterator2array(Object[] objects) {
        // when
        Object[] result = Util.iterator2array(Arrays.stream(objects).iterator());

        // then
        assertThat(result).containsExactly(objects);
    }

    private static Stream<Object[]> objectArrayProvider() {
        // given
        return Stream.of(
            new Object[] { new Object[] { new Object() } },
            new Object[] { new Object[] { new Object(), new Object() } });
    }

    /**
     * Tests the method {@link Util#figureEnumeration2array(FigureEnumeration)}.
     * This tests for an enumeration consisting of 0, 1 and 2 figures.
     *
     * @param k how many figures should be in the enumeration.
     */
    @ParameterizedTest
    @ValueSource(ints = { 0, 1, 2 })
    public void testFigureEnumeration2array(int k) {
        // Given
        FigureEnumeration testEnumeration = mock(FigureEnumeration.class);

        List<Figure> testFigures = new ArrayList<>();

        when(testEnumeration.nextElement()).thenAnswer((Answer<Figure>) invocation -> {
            Figure testFigure = mock(Figure.class);
            testFigures.add(testFigure);
            return testFigure;
        });
        when(testEnumeration.hasMoreElements()).thenAnswer(new Answer<Boolean>() {
            int _counter = 0;

            @Override
            public Boolean answer(InvocationOnMock invocation) {
                return _counter++ < k;
            }
        });

        // When
        Object[] result = Util.figureEnumeration2array(testEnumeration);

        // Then
        assertThat(result).containsExactly(testFigures.toArray());
    }
}