package com.atlassian.stash.internal.event;

import com.atlassian.event.api.EventListener;
import com.atlassian.event.api.EventPublisher;
import com.atlassian.event.internal.ListenerHandlerConfigurationImpl;
import org.junit.Test;
import org.mockito.Mockito;

import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;

public class EventListenerRegistrarTest {

    private static final String EVENT_PUBLISHER = "eventPublisher";

    @Test
    public void testFullStartupLifecycle() throws Exception {
        EventListenerRegistrar registrar = new EventListenerRegistrar(EVENT_PUBLISHER, new ListenerHandlerConfigurationImpl());
        EventPublisher eventPublisher = Mockito.mock(EventPublisher.class);
        // Use the same name for a global bean and plugin module and make sure both are registered separately
        String beanName = "c";

        // Beans that are registered too early need to be stored until we have the eventPublisher
        MockModule bean1 = new MockModule();
        MockModule bean2 = new MockModule();
        registrar.postProcessBeforeInitialization(bean1, beanName);
        registrar.postProcessBeforeInitialization(bean2, "e");

        // Unregister one of the global modules to test this logic
        registrar.postProcessBeforeDestruction(null, "e");

        // After we load the eventPublisher all the previous beans should be registered
        registrar.postProcessAfterInitialization(eventPublisher, "eventPublisher");
        verify(eventPublisher).register(bean1);
        verify(eventPublisher, times(0)).register(bean2);

        // Every module after the first postProcessAfterInitialization() should be registered immediately

        // Verify that we never published again
        eventPublisher = Mockito.mock(EventPublisher.class);
        registrar.postProcessAfterInitialization(eventPublisher, "eventPublisher");
        verifyZeroInteractions(eventPublisher);
    }

    private static class MockModule {
        @EventListener
        public void onSomething(Object event) {
        }
    }
}
