package com.atlassian.stash.internal.event;

import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Used to mark methods which are listening to <i>internal</i> events, which are broadcast using Spring's
 * {@code ApplicationEventPublisher} rather than the Atlassian Events framework.
 * <p>
 * This annotation is an alternative for Spring's {@code EventListener}. The primary reason for <i>not</i>
 * using Spring's annotation is that Atlassian Events uses an annotation with the same name, which makes it
 * harder to differentiate between Spring listeners and Atlassian Events listeners. This annotation reads
 * more obviously when perusing or reviewing source.
 *
 * Note: this annotation is not being used in 4.2 because methods annotated with @InternalEventListeners are
 * only called when they're top-level beans in the application context. Nested beans do not get called.
 * See BSERVDEV-11246.
 *
 * @since 4.2
 */
@EventListener
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface InternalEventListener {

    /**
     * The event classes that this listener handles.
     * <p>
     * If this attribute is specified with a single value, the annotated method may optionally accept a
     * single parameter. However, if this attribute is specified with multiple values, the annotated
     * method must <em>not</em> declare any parameters.
     */
    @AliasFor(annotation = EventListener.class, attribute = "classes")
    Class<?>[] classes() default {};

    /**
     * Spring Expression Language (SpEL) attribute used for making the event handling conditional.
     * <p>
     * Default is {@code ""}, meaning the event is always handled.
     */
    @AliasFor(annotation = EventListener.class, attribute = "condition")
    String condition() default "";

    /**
     * Alias for {@link #classes}.
     */
    @AliasFor(annotation = EventListener.class, attribute = "classes")
    Class<?>[] value() default {};
}
