package eu.dnetlib.msro.workflows.nodes;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.sarasvati.Engine;
import com.googlecode.sarasvati.NodeToken;

import eu.dnetlib.enabling.locators.UniqueServiceLocator;
import eu.dnetlib.enabling.tools.blackboard.BlackboardClientHandler;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJob;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJobImpl;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJobRegistry;
import eu.dnetlib.msro.workflows.nodes.blackboard.BlackboardWorkflowJobListener;
import eu.dnetlib.msro.workflows.util.WorkflowsConstants;

public abstract class BlackboardJobNode extends SarasvatiJobNode {

	@Resource
	private UniqueServiceLocator serviceLocator;

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

	/**
	 * blackboard handler.
	 */
	@Resource
	private BlackboardClientHandler blackboardClientHandler;

	/**
	 * blackboard job registry.
	 */
	@Resource
	private BlackboardJobRegistry jobRegistry;

	@Override
	public void execute(final Engine engine, final NodeToken token) {
		super.execute(engine, token);

		log.info("executing blackboard node");

		try {
			token.getEnv().setAttribute(WorkflowsConstants.BLACKBOARD_IS_BLACKBOARD, true);

			final String serviceId = obtainServiceId(token);
			if (StringUtils.isBlank(serviceId)) {
				token.getEnv().setAttribute(WorkflowsConstants.SYSTEM_HAS_FAILED, true);
				final String msg = "cannot locate target service profile: " + serviceId;
				token.getEnv().setAttribute(WorkflowsConstants.SYSTEM_ERROR, msg);
				log.error(msg);
				engine.complete(token, "failed");
				return;
			}

			final BlackboardJob job = blackboardClientHandler.newJob(serviceId);

			token.getEnv().setTransientAttribute(WorkflowsConstants.BLACKBOARD_JOB, job);
			token.getEnv().setAttribute(WorkflowsConstants.BLACKBOARD_SERVICE_ID, ((BlackboardJobImpl) job).getServiceId());
			prepareJob(job, token);

			jobRegistry.registerJobListener(job, generateBlackboardListener(engine, token));

			blackboardClientHandler.assign(job);

		} catch (final Throwable e) {
			token.getEnv().setAttribute(WorkflowsConstants.SYSTEM_HAS_FAILED, true);
			token.getEnv().setAttribute(WorkflowsConstants.SYSTEM_ERROR, "cannot prepare blackboard job: " + e);
			engine.complete(token, "failed");
			log.error("cannot prepare blackboard job", e);
		}
	}

	abstract protected String obtainServiceId(NodeToken token);

	abstract protected void prepareJob(final BlackboardJob job, final NodeToken token) throws Exception;

	protected BlackboardWorkflowJobListener generateBlackboardListener(final Engine engine, final NodeToken token) {
		return new BlackboardWorkflowJobListener(engine, token);
	}

	public UniqueServiceLocator getServiceLocator() {
		return serviceLocator;
	}

}
