package eu.dnetlib.enabling.tools.blackboard;

import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.springframework.beans.factory.annotation.Required;
import org.xml.sax.SAXException;

import eu.dnetlib.enabling.tools.Enableable;
import eu.dnetlib.enabling.tools.StringOpaqueResource;

/**
 * Common blackboard notification handler. This notification handler processes only message with ...BODY.BLACKBOARD.LAST* as topic.
 * 
 * @param <T>
 *            type of blackboard handler used to extract the blackboard message (client or server)
 * @author marko
 * 
 */
public abstract class AbstractBlackboardNotificationHandler<T extends BlackboardHandler> implements NotificationHandler, Enableable {

	/**
	 * blackboard handler.
	 */
	private T blackboardHandler;

	/**
	 * true if enabled.
	 */
	private boolean enabled = true;

	/**
	 * Executor handles the notified request in a dedicated thread and allows to return immediately.
	 */
	private Executor executor = Executors.newCachedThreadPool();

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.data.mdstore.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) {
		if (!topic.contains("BODY.BLACKBOARD.LAST")) return;

		executor.execute(new Runnable() {

			@Override
			public void run() {
				try {
					processJob(blackboardHandler.getJob(new StringOpaqueResource(profile)));
				} catch (final XPathExpressionException e) {
					throw new IllegalStateException(e);
				} catch (final SAXException e) {
					throw new IllegalStateException(e);
				} catch (final IOException e) {
					throw new IllegalStateException(e);
				} catch (final ParserConfigurationException e) {
					throw new IllegalStateException(e);
				}
			}
		});
	}

	/**
	 * Subclassess override this to process incoming blackboard jobs.
	 * 
	 * @param job
	 *            blackboard job
	 */
	protected abstract void processJob(BlackboardJob job);

	public T getBlackboardHandler() {
		return blackboardHandler;
	}

	@Required
	public void setBlackboardHandler(final T blackboardHandler) {
		this.blackboardHandler = blackboardHandler;
	}

	@Override
	public boolean isEnabled() {
		return enabled;
	}

	@Override
	public void setEnabled(final boolean enabled) {
		this.enabled = enabled;
	}

}
