package de.renew.net.inscription.transition;

import java.util.Collection;
import java.util.stream.Stream;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import de.renew.engine.searcher.Occurrence;
import de.renew.engine.searcher.Searcher;
import de.renew.expression.VariableMapper;
import de.renew.net.NetInstance;
import de.renew.unify.Impossible;

import static org.assertj.core.api.Assertions.assertThat;


/**
 * Test class for {@link RangeEnumeratorInscription}.
 * Tests only the relevant (non-trivial) methods.
 */
class RangeEnumeratorInscriptionTest extends InscriptionTest {
    /**
     * Setup method to initialize this test environment.
     */
    @BeforeEach
    void setUp() throws Impossible {
        super.setUp();
    }

    /**
     * Test method for {@link RangeEnumeratorInscription#makeOccurrences(VariableMapper, NetInstance, Searcher)}.
     *
     * @param isBound true if bound should be checked.
     * @param first the first index.
     * @param last the last index.
     * @throws Impossible if it is impossible to make the {@code Occurrence}s.
     */
    @ParameterizedTest
    @MethodSource
    void testMakeOccurrences(boolean isBound, int first, int last) throws Impossible {
        //given
        RangeEnumeratorInscription inscription =
            new RangeEnumeratorInscription(_mockExpression, first, last, isBound, _transition);

        //when
        Collection<Occurrence> occurrences =
            inscription.makeOccurrences(_mapper, _mockNetInstance, _searcher);

        //then
        RangeEnumeratorOccurrence expectedOccurrence = new RangeEnumeratorOccurrence(
            _mockExpression, isBound, _mapper, first, last,
            _mockNetInstance.getInstance(_transition));
        assertThat(occurrences).isNotNull().hasSize(1);
        assertThat(occurrences).first().isInstanceOf(RangeEnumeratorOccurrence.class)
            .usingRecursiveComparison().isEqualTo(expectedOccurrence);
    }

    static Stream<Arguments> testMakeOccurrences() {
        return Stream.of(
            Arguments.arguments(true, 0, 1), Arguments.arguments(false, 0, 1),
            Arguments.arguments(true, 0, 0), Arguments.arguments(false, 0, 0));
    }
}