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

import net.ranides.assira.awt.AWTInvoker;

/**
 * Obserwator, który po otrzymaniu informacji o zdarzeniu, wywołuje obsługuje 
 * w wątku AWT za pomocą {@link AWTInvoker#run}.
 * @param <T> 
 * @see AWTInvoker
 * @author ranides
 */
public class SwingEventListener<T extends Event> implements EventListener<T> {
    
    private final boolean sync;
    private final EventListener<T> handler;

    /**
     * Tworzy nowy obserwator, który wywołuje obsługę {@code handler}'a w wątku
     * AWT. Jeśli argument {@code sync=true} obserwator blokuje również wątek
     * routera do momentu, aż zdarzenie zostanie przez AWT obsłużone. 
     * @see javax.swing.SwingUtilities#invokeAndWait
     * @param handler
     * @param sync 
     */
    public SwingEventListener(EventListener<T> handler, boolean sync) {
        this.handler = handler;
        this.sync = sync;
    }
    
    /**
     * Tworzy nowy obserwator, który wywołuje obsługę {@code handler}'a w wątku
     * AWT. Wątek routera nie jest blokowany przez obsługę zdarzenia - obserwator
     * kończy działanie natychmiast po przekazaniu zdarzenia do kolejki AWT.
     * @see javax.swing.SwingUtilities#invokeLater
     * @param handler 
     */
    public SwingEventListener(EventListener<T> handler) {
        this(handler, false);
    }

    @Override
    public void handleEvent(final T event) {
        AWTInvoker.run(sync, handler, event);
    }
    
    /**
     * Metoda statyczna tworząca listener za pomocą konstruktora 
     * {@link #SwingEventListener(EventListener) SwingEventListener(EventListener)}.
     * Pozwala skrócić zapis, oszczędzając pisania typu parametru SwingEventListener'a - 
     * kompilator potrafi go wydedukować nawet w Javie wcześniejszej niż 1.7
     * @param <E>
     * @param listener
     * @return 
     */
    public static <E extends Event> SwingEventListener<E> wrap(EventListener<E> listener) {
        return new SwingEventListener<>(listener);
    }
    
    /**
     * Metoda statyczna tworząca listener za pomocą konstruktora 
     * {@link #SwingEventListener(EventListener) SwingEventListener(EventListener)}.
     * Pozwala skrócić zapis, oszczędzając pisania typu parametru SwingEventListener'a - 
     * kompilator potrafi go wydedukować nawet w Javie wcześniejszej niż 1.7
     * @param <E>
     * @param listener
     * @param sync 
     * @return 
     */
    public static <E extends Event> SwingEventListener<E> wrap(EventListener<E> listener, boolean sync) {
        return new SwingEventListener<>(listener, sync);
    }
    /**
     * Metoda statyczna tworząca listener za pomocą konstruktora 
     * {@link #SwingEventListener(EventListener) SwingEventListener(EventListener)}.
     * Pozwala skrócić zapis, oszczędzając pisania typu parametru SwingEventListener'a - 
     * kompilator potrafi go wydedukować nawet w Javie wcześniejszej niż 1.7
     * @param <E>
     * @param listener
     * @param sync 
     * @return 
     */
    public static <E extends Event> SwingEventListener<E> wrap(boolean sync, EventListener<E> listener) {
        return new SwingEventListener<>(listener, sync);
    }

}
