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

import java.io.IOException;
import java.io.Serializable;
import net.ranides.assira.io.IOEvent;

/**
 *
 * @author ranides
 */
public final class Events {
    
    private Events() {
        /* utility class */
    }

    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(Throwable cause) {
        if(cause instanceof IOException) {
            return IOEvent.failure((IOException)cause);
        }
        return new Failure(cause);
    }

    public static class Dispose implements Event {
		
        protected final EventRouter router;

        protected Dispose(EventRouter router) {
            this.router = router;
        }
        
        public final EventRouter router() {
            return router;
        }
        
        @Override
        public String toString() {
            return "CoreEvent:Dispose<" + router + ">";
        }
        
    }

    /**
     * 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 {
		
		private static final long serialVersionUID = 1L;
        
        protected Stop(EventRouter router) {
            super(router);
        }
        
        @Override
        public String toString() {
            return "CoreEvent:Stop<" + 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 implements Event {
		
        protected final EventRouter router;

        protected Shutdown(EventRouter router) {
            this.router = router;
        }
        
        public final EventRouter router() {
            return router;
        }
        
        @Override
        public String toString() {
            return "CoreEvent:Shutdown<" + router + ">";
        }

    }

    /**
     * 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 {
		
		private static final long serialVersionUID = 1L;
        
        protected Interrupt(EventRouter name) {
            super(name);
        }
        
        @Override
        public String toString() {
            return "CoreEvent:Interrupt<" + router + ">";
        }
        
    }

    public static class Failure implements Event, Serializable {
		
		private static final long serialVersionUID = 1L;

        private final Throwable cause;

        protected Failure(Throwable cause) {
            this.cause = cause;
        }
        
        public Throwable cause() {
            return cause;
        }
        
        @Override
        public String toString() {
            return "CoreEvent:Failure: " + cause;
        }
    }

}
