package cz.cuni.amis.utils.listener;

import java.util.HashMap;
import java.util.Map;

/**
 * Map of the listeners according to some key.
 * <br><br>
 * Comes in handy when you need the map of Listeners&lt;? extends Listener&gt; and work
 * with them (otherwise you're doomed to write tedious and ugly for-cycles forever).
 * <br><br>
 * And believe me, you don't want to parametrize the class more further the 'Key'...
 * ... just remember it must be used with instances of 'Listener'.
 *  
 * 
 * @author Jimmy
 */
@SuppressWarnings("unchecked")
public class ListenersMap<Key> {

	/**
	 * Map of the listeners, key is the event class where the listener is hooked to.
	 */
	private Map<
				Key, 
	            Listeners<IListener>
	 		   > listenersMap = 
	 				new HashMap<
	 					Key, 
	 				 	Listeners<IListener>
				   	>();
	
	public void add(Key key, IListener listener) {
		synchronized(listenersMap) {
			Listeners<IListener> listeners = listenersMap.get(key);
			if (listeners == null) {
				listeners = new Listeners<IListener>();
				listenersMap.put(key, listeners);
			}
			listeners.addWeakListener(listener);
		}
	}
	
	public boolean isListening(IListener listener) {
		synchronized (listenersMap) {
			for (Key key : listenersMap.keySet()) {
				if (isListening(key, listener)) return true;
			}
			return false;		
		}
	}
	
	public boolean isListening(Key key, IListener listener) {
		synchronized(listenersMap) {
			Listeners<IListener> listeners = listenersMap.get(key);
			if (listeners == null) return false;
			return listeners.isEqualListening(listener);
		}
	}
	
	public void remove(IListener listener) {
		synchronized(listenersMap) {
			for (Key key : listenersMap.keySet()) {
				remove(key, listener);
			}			
		}
	}
	
	public void remove(Key key, IListener listener) {
		synchronized(listenersMap) {
			Listeners<IListener> listeners = listenersMap.get(key);
			if (listeners == null) return;
			listeners.removeListener(listener);
		}
	}
	
	public void notify(Listeners.ListenerNotifier<IListener> notifier) {
		synchronized(listenersMap) {
			for (Key key : listenersMap.keySet()) {
				notify(key, notifier);
			}			
		}
	}
	
	public void notify(Key key, Listeners.ListenerNotifier<IListener> notifier) {
		synchronized(listenersMap) {
			Listeners<IListener> listeners = listenersMap.get(key);
			if (listeners == null) return;
			listeners.notify(notifier);
		}
	}
	
	
}
