package de.renew.application;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

import de.renew.plugin.ServiceLookupException;
import de.renew.plugin.ServiceLookupInfrastructure;
import de.renew.simulator.api.ISimulatorExtensions;
import de.renew.simulator.api.SimulatorExtensions;
import de.renew.simulatorontology.simulation.SimulatorExtension;

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

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class SimulatorExtensionsTest {

    @Spy
    private ISimulatorExtensions _simulatorExtensions = SimulatorExtensionsProvider.provider();

    @Mock
    private SimulatorExtension _extension;

    private MockedStatic<ServiceLookupInfrastructure> _sliStaticMock;

    @BeforeEach
    public void setUp() throws ServiceLookupException {

        ServiceLookupInfrastructure sliMock = mock(ServiceLookupInfrastructure.class);
        when(sliMock.getFirstServiceProvider(ISimulatorExtensions.class))
            .thenReturn(_simulatorExtensions);

        _sliStaticMock = Mockito.mockStatic(ServiceLookupInfrastructure.class);
        _sliStaticMock.when(ServiceLookupInfrastructure::getInstance).thenReturn(sliMock);
    }

    @AfterEach
    public void tearDown() {
        _simulatorExtensions.cleanup();
        _sliStaticMock.close();
    }

    @Test
    public void testAddExtension() {
        //when
        SimulatorExtensions.addExtension(_extension);

        //then
        assertThat(_simulatorExtensions.getSimulationExtensions()).containsExactly(_extension);
    }

    @Test
    public void testAddExtensionOrder() {
        //given
        SimulatorExtension extension2 = mock(SimulatorExtension.class);

        //when
        SimulatorExtensions.addExtension(_extension);
        SimulatorExtensions.addExtension(extension2);

        //then
        assertThat(_simulatorExtensions.getSimulationExtensions())
            .containsExactly(_extension, extension2);
    }

    @Test
    public void testRemoveExtension() {
        //given
        SimulatorExtensions.addExtension(_extension);
        assertThat(_simulatorExtensions.getSimulationExtensions()).containsExactly(_extension);

        //when
        SimulatorExtensions.removeExtension(_extension);

        //then
        assertThat(_simulatorExtensions.getSimulationExtensions()).isEmpty();
    }
}