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

package net.ranides.assira.events;

import java.util.Collection;

/**
 * Klasa EventRouter propaguje zasygnalizowane zdarzenia do odbiorców.
 * Każdy router potrafi nie tylko rozsyłać zdarzenia, ale również odbierać -
 * implementuje interfejs {@code EventListener<Event>} i może być rejestrowany
 * jako obserwator. Każde zdarzenie można skierować do routera na dwa sposoby:
 * <ul>
 *  <li>metodą {@link #signalEvent} - wtedy mamy możliwość sprawdzenia,
 * czy komunikat udało się dostarczyć</li>
 *  <li>metodą {@link EventListener#handleEvent} - wtedy takiej możliwości nie
 * posiadamy</li>
 * </ul>
 * @author ranides
 */
public interface EventRouter extends EventListener<Event> {

    /**
     * Rejestruje obserwatora, który otrzyma wszystkie zdarzenia o podanym typie.
     * <div class="message-note">thread-safe method</div>
     * @param <T>
     * @param event
     * @param listener
     */
    <T extends Event> void addEventListener(Class<T> event, EventListener<? super T> listener);

    /**
     * Usuwa obserwatora, którego wcześniej zarejestrowano dla zdarzeń o
     * podanym typie. Jeśli zajestrowano go również dla zdarzeń o innych typach
     * - zostają one nadal. Jeśli zarejestrowano go wielokrotnie - musi zostać
     * usunięty również wielokrotnie.
     * <div class="message-note">thread-safe method</div>
     * @param <T>
     * @param event
     * @param listener
     */
    <T extends Event> void removeEventListener(Class<T> event, EventListener<? super T> listener);

    /**
     * Usuwa wszystkie zarejestrowane obserwatory.
     * <div class="message-note">thread-safe method</div>
     */
    void removeAllEventListeners();

    Collection<EventBinding<?>> getEventListeners();
    
    int getEventListenersCount();

    /**
     * Sygnalizuje podane zdarzenie rozsyłając komunikat do wszystkich obserwatorów.
     * Jeśli rozesłanie komunikatu nie jest możliwe, zwraca {@code false}.
     * @param event
     * @return true - jeśli zdarzenie może być przekazane odbiorcom.
     */
    boolean signalEvent(Event event);

    /**
     * Kończy działanie routera i zwalnia wszystkie zasoby.
     * <div class="message-note">thread-safe method</div>
     */
    void dispose();

}
