package eu.dnetlib.actionmanager.wf;

import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import javax.annotation.Resource;

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

import com.googlecode.sarasvati.Engine;
import com.googlecode.sarasvati.Graph;
import com.googlecode.sarasvati.GraphProcess;
import com.googlecode.sarasvati.mem.MemGraphProcess;

import eu.dnetlib.actionmanager.is.ISClient;
import eu.dnetlib.actionmanager.rmi.ActionManagerException;
import eu.dnetlib.workflow.GraphProcessRegistry;

public class ActionManagerWorkflowLauncher {
	/**
	 * workflow process registry.
	 */
	private GraphProcessRegistry processRegistry;
	/**
	 * workflow graphs.
	 */
	private Graph commitGraph;
	private Graph deleteGraph;

	private Executor executor = Executors.newCachedThreadPool();

	private ISClient infomationServiceClient;

	/**
	 * workflow engine.
	 */
	@Resource
	private transient Engine engine;

	private String actionTable;
	private String dataTable;

	private static final Log log = LogFactory.getLog(ActionManagerWorkflowLauncher.class); // NOPMD by marko on 11/24/08 5:02 PM
	public static final String ALL_SETS = "__ALL__";

	public void executeDelete(final String set, final Callable<?> callbackCompleted, final Callable<?> callbackFailed) throws ActionManagerException {
		log.info("Starting clean-wf; set=" + set);
		execute(deleteGraph, set, callbackCompleted, callbackFailed);
	}

	public void executeCommit(final String set, final Callable<?> callbackCompleted, final Callable<?> callbackFailed) throws ActionManagerException {
		log.info("Starting commit-wf; set=" + set);
		execute(commitGraph, set, callbackCompleted, callbackFailed);
	}

	private void execute(final Graph graph, final String set, final Callable<?> callbackCompleted, final Callable<?> callbackFailed)
			throws ActionManagerException {
		if (set != null && !set.equals(ALL_SETS) && !infomationServiceClient.existsSet(set)) {
			throw new ActionManagerException("Missing set " + set);
		}

		executor.execute(new Runnable() {
			@Override
			public void run() {
				final GraphProcess process = new MemGraphProcess(graph);

				processRegistry.registerProcess(process);

				if (set != null && !set.equals(ALL_SETS)) {
					process.getEnv().setAttribute("set", set);
				}
				process.getEnv().setAttribute("actionTable", actionTable);
				process.getEnv().setAttribute("dataTable", dataTable);
				process.getEnv().setTransientAttribute("callbackCompleted", callbackCompleted);
				process.getEnv().setTransientAttribute("callbackFailed", callbackFailed);

				engine.startProcess(process);
			}
		});
	}

	public Engine getEngine() {
		return engine;
	}

	public void setEngine(final Engine engine) {
		this.engine = engine;
	}

	public Graph getCommitGraph() {
		return commitGraph;
	}

	@Required
	public void setCommitGraph(Graph commitGraph) {
		this.commitGraph = commitGraph;
	}

	public Graph getDeleteGraph() {
		return deleteGraph;
	}

	@Required
	public void setDeleteGraph(Graph deleteGraph) {
		this.deleteGraph = deleteGraph;
	}

	public String getActionTable() {
		return actionTable;
	}

	@Required
	public void setActionTable(String actionTable) {
		this.actionTable = actionTable;
	}

	public String getDataTable() {
		return dataTable;
	}

	@Required
	public void setDataTable(String dataTable) {
		this.dataTable = dataTable;
	}

	public GraphProcessRegistry getProcessRegistry() {
		return processRegistry;
	}

	@Required
	public void setProcessRegistry(GraphProcessRegistry processRegistry) {
		this.processRegistry = processRegistry;
	}

	public ISClient getInfomationServiceClient() {
		return infomationServiceClient;
	}

	@Required
	public void setInfomationServiceClient(ISClient infomationServiceClient) {
		this.infomationServiceClient = infomationServiceClient;
	}

}
