package com.atlassian.stash.internal.plugin;

import com.atlassian.event.api.EventListener;
import com.atlassian.event.api.EventPublisher;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.*;

/**
 * Unit test to test whether classes annotated with @EventListener or implementing the EventListener interface
 * are automatically registered and unregistered with the application context lifecycle.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/spring/eventlistener-test-context.xml"})
public class EventListenerRegistrationTest {
    /**
     * Example event class
     */
    public static class ExampleEvent {
        public String value;

        public ExampleEvent(String value) {
            this.value = value;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            if (!super.equals(o)) {
                return false;
            }

            ExampleEvent that = (ExampleEvent) o;

            if (value != null ? !value.equals(that.value) : that.value != null) {
                return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int result = super.hashCode();
            result = 31 * result + (value != null ? value.hashCode() : 0);
            return result;
        }
    }

    /**
     * Example event listener that uses the @EventListener annotation. A bean of this type is defined in eventlistener-test-context.xml
     */
    public static class ExampleAnnotationBasedEventListener {
        public ExampleEvent event;
        
        @EventListener
        public void onEvent(ExampleEvent event) {
            this.event = event;
        }
        
        public void reset() {
            this.event = null;
        }
        
    }
    
    @Autowired
    private ExampleAnnotationBasedEventListener annotationListener;

    @Autowired
    private EventPublisher eventPublisher;
    
    @After
    public void resetListeners() {
        annotationListener.reset();
    }
    
    @Test
    public void testPublishEvent() {
        ExampleEvent event = new ExampleEvent("test-event");
        
        eventPublisher.publish(event);

        assertEquals(event, annotationListener.event);
    }
}
