/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.events;

/**
 *
 * @author ranides
 */
public abstract class CoreEvent implements Event {

    private final EventListener source;

    public EventListener<?> source() {
        return source;
    }

    protected CoreEvent(EventListener source) {
        this.source = source;
    }

    @Override
    public String toString() {
        return "CoreEvent." + getClass().getSimpleName() + "<" + source() + ">";
    }

    public static Dispose dispose(EventRouter source) {
        return new Dispose(source);
    }

    public static Stop stop(EventRouter source) {
        return new Stop(source);
    }

    public static Shutdown shutdown(EventRouter source) {
        return new Shutdown(source);
    }

    public static Interrupt interrupt(EventRouter source) {
        return new Interrupt(source);
    }

    public static Failure failure(EventListener<?> source, Throwable cause) {
        return new Failure(source, cause);
    }

    public static class Dispose extends CoreEvent {
        protected Dispose(EventRouter router) {
            super(router);
        }
        @Override
        public EventRouter source() {
            return (EventRouter)super.source();
        }
    }

    /**
     * Zdarzenie, które może zostać wysłane do routera, w celu zakończenia jego pracy.
     * Router rozsyła to zdarzenie do obserwatorów, tak samo jak każde inne.
     * Router kończy działanie tylko jeśli jako źródło podany jest referencja do
     * routera.
     */
    public static class Stop extends Dispose {
        protected Stop(EventRouter router) {
            super(router);
        }
    }

    /**
     * Zdarzenie wysyłane do wszystkich zainteresowanych obserwatorów routera.
     * Informuje, że router zakończył swoją pracę. Jeśli router zakończył pracę
     * z powodu przerwania (failure), to komunikat podanej klasy również jest
     * rozsyłany (dokładniej: jego klasa pochodna).
     * @see InterruptEvent
     */
    public static class Shutdown extends CoreEvent {
        protected Shutdown(EventRouter source) {
            super(source);
        }

    }

    /**
     * Zdarzenie wysyłane do wszystkich zainteresowanych obserwatorów routera.
     * Informuje, że router zakończył swoją pracę z powodu wymuszenia - nastąpiło
     * przerwanie i wyjątek {@link InterruptedException}.
     */
    public static class Interrupt extends Shutdown {
        protected Interrupt(EventRouter name) {
            super(name);
        }
    }

    public static class Failure extends CoreEvent {

        private final Throwable cause;

        protected Failure(EventListener source, Throwable cause) {
            super(source);
            this.cause = cause;
        }
        public Throwable cause() {
            return cause;
        }
    }

}
