package eu.dnetlib.enabling.tools.blackboard;

import java.util.Collection;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.core.task.TaskExecutor;

import eu.dnetlib.enabling.actions.AbstractSubscriptionAction;
import eu.dnetlib.enabling.tools.Enableable;
import eu.dnetlib.enabling.tools.EnableableEnumerator;

public class NotificationHandlerChainImpl implements NotificationHandlerChain {
	
	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(NotificationHandlerChain.class); // NOPMD by marko on 11/24/08 5:02 PM

	/**
	 * notification handler chain.
	 */
	private Collection<NotificationHandler> handlers;

	/**
	 * task executor used for invoking the handlers.
	 */
	private TaskExecutor handlerExecutor;

	@Resource
	private NotificationHistory notificationHistory;

	@Resource
	private EnableableEnumerator enableableEnumerator;

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.enabling.tools.blackboard.NotificationHandler#notified(java.lang.String, java.lang.String,
	 *      java.lang.String, java.lang.String)
	 */
	@Override
	public void notified(final String subscrId, final String topic, final String rsId, final String profile) {

		for (final NotificationHandler handler : handlers) {

			try {
				if (handler instanceof AbstractSubscriptionAction)
					if (topic.startsWith(((AbstractSubscriptionAction) handler).getTopicPrefix()))
						if (!((Enableable) handler).isEnabled()) {
							for (Map.Entry<String, Enableable> entry : enableableEnumerator.getAllEnableables().entrySet()) {
								if (entry.getValue() == handler) {
									NotificationInfo info = new NotificationInfo();
									info.setName(entry.getKey());
									info.setProfile(profile);
									info.setRsId(rsId);
									info.setSubscrId(subscrId);
									info.setTopic(topic);
									notificationHistory.saveNotification(info);
								}
							}
							continue;
						}
					
				delegateNotification(subscrId, topic, rsId, profile, handler);
			} catch (final RuntimeException e) {
				log.fatal("error processing notification handler " + handler, e);
			}
		}
	}

	@Override
	public void delegateNotification(final String subscrId, final String topic, final String rsId, final String profile, final NotificationHandler handler) {

		handlerExecutor.execute(new Runnable() {
			@Override
			public void run() {
				handler.notified(subscrId, topic, rsId, profile);
			}
		});
	}

	public Collection<NotificationHandler> getHandlers() {
		return handlers;
	}

	@Required
	public void setHandlers(final Collection<NotificationHandler> handlers) {
		this.handlers = handlers;
	}

	public TaskExecutor getHandlerExecutor() {
		return handlerExecutor;
	}

	@Required
	public void setHandlerExecutor(TaskExecutor handlerExecutor) {
		this.handlerExecutor = handlerExecutor;
	}
}
