package de.renew.net.event;

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.InOrder;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

import de.renew.engine.thread.SimulationThreadPool;

import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class PlaceEventTest {
    @Mock
    private PlaceEvent _mockPlaceEvent;

    @Mock
    private TokenEvent _mockTokenEvent;

    @Spy
    private PlaceEventListener _listener;

    private MockedStatic<SimulationThreadPool> _simulationThreadPoolMockedStatic;

    @BeforeEach
    void setUp() {
        _simulationThreadPoolMockedStatic = mockStatic(SimulationThreadPool.class);
        _simulationThreadPoolMockedStatic.when(SimulationThreadPool::isSimulationThread)
            .thenReturn(true);
    }

    @AfterEach
    public void tearDown() {
        _simulationThreadPoolMockedStatic.close();
    }

    @Test
    public void testEventFlow() {
        //given
        PlaceEventListenerSet producer = new PlaceEventListenerSet();
        when(_listener.wantSynchronousNotification()).thenReturn(true);

        //when
        producer.addPlaceEventListener(_listener);
        producer.markingChanged(_mockPlaceEvent);
        producer.tokenAdded(_mockTokenEvent);
        producer.tokenTested(_mockTokenEvent);
        producer.tokenUntested(_mockTokenEvent);
        producer.tokenRemoved(_mockTokenEvent);


        //then
        InOrder inOrder = inOrder(_listener);

        inOrder.verify(_listener).markingChanged(_mockPlaceEvent);

        inOrder.verify(_listener).tokenAdded(_mockTokenEvent);

        inOrder.verify(_listener).tokenTested(_mockTokenEvent);

        inOrder.verify(_listener).tokenUntested(_mockTokenEvent);

        inOrder.verify(_listener).tokenRemoved(_mockTokenEvent);
    }
}