/*******************************************************************************
 * Copyright (C) 2009 Hajo Nils Krabbenhoeft, INB, University of Luebeck
 *
 *  Modifications to the initial code base are copyright of their
 *  respective authors, or their employers as appropriate.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 ******************************************************************************/

package net.sf.taverna.t2.activities.externaltool;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroup;
import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanism;
import net.sf.taverna.t2.annotation.Annotated;
import net.sf.taverna.t2.annotation.annotationbeans.MimeType;
import net.sf.taverna.t2.reference.ExternalReferenceSPI;
import net.sf.taverna.t2.reference.ReferenceService;
import net.sf.taverna.t2.reference.T2Reference;
import net.sf.taverna.t2.reference.WorkflowRunIdEntity;
import net.sf.taverna.t2.workflowmodel.EditException;
import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity;
import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityInputPort;
import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort;
import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback;

import org.apache.log4j.Logger;

import de.uni_luebeck.inb.knowarc.usecases.ScriptInput;
import de.uni_luebeck.inb.knowarc.usecases.ScriptInputUser;
import de.uni_luebeck.inb.knowarc.usecases.ScriptOutput;
import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
import de.uni_luebeck.inb.knowarc.usecases.invocation.InvocationException;
import de.uni_luebeck.inb.knowarc.usecases.invocation.UseCaseInvocation;

/**
 * This is the main class of the use case activity plugin. Here we store the
 * configuration and the description of a use case activity, configure the input
 * and output port and provide use case activity invocation
 *
 * @author Hajo Nils Krabbenhoeft
 */
public class ExternalToolActivity extends AbstractAsynchronousActivity<ExternalToolActivityConfigurationBean> {

	public static final String URI = "http://ns.taverna.org.uk/2010/activity/tool";

	private static final String STDERR = "STDERR";

	private static final String STDOUT = "STDOUT";

	private static final String STDIN = "STDIN";

	private static Logger logger = Logger.getLogger(ExternalToolActivity.class);

	private ExternalToolActivityConfigurationBean configurationBean;
	private UseCaseDescription mydesc;

	private List<InvocationCreator> invocationCreators;

	/**
	 * Add the given MIME types to the given input/output port.
	 *
	 * @param annotated
	 *            The port to which to add the MIME types.
	 * @param mimeTypes
	 *            A list of Strings specifying the MIME types to add.
	 */
	private void addMimeTypes(Annotated<?> annotated, List<String> mimeTypes) {
		for (String mimeType : mimeTypes) {
			MimeType mimeTypeAnnotation = new MimeType();
			mimeTypeAnnotation.setText(mimeType);
			try {
				getEdits().getAddAnnotationChainEdit(annotated, mimeTypeAnnotation).doEdit();
			} catch (EditException e) {
				Logger.getLogger(ExternalToolActivity.class).error(e);
			}
		}
	}

	/**
	 * Create a new input port with the given name, depth, element class and
	 * MIME types.
	 *
	 * @param portName
	 *            Name of the new port
	 * @param portDepth
	 *            Depth of the new port
	 * @param translatedElementClass
	 *            Which class of elements would this port like?
	 * @param mimeTypes
	 *            Accepted mime types for this port
	 */
	private void addInputWithMime(String portName, int portDepth, Class<?> translatedElementClass, List<String> mimeTypes) {
		List<Class<? extends ExternalReferenceSPI>> handledReferenceSchemes = Collections.emptyList();
		ActivityInputPort inputPort = getEdits().createActivityInputPort(portName, portDepth, true, handledReferenceSchemes,
				translatedElementClass);
		inputPorts.add(inputPort);
		if (mimeTypes != null) {
			addMimeTypes(inputPort, mimeTypes);
		}
	}

	/**
	 * Create a new output port with the given MIME types
	 *
	 * @param portName
	 *            Name of the new port
	 * @param portDepth
	 *            Depth of the new port
	 * @param mimeTypes
	 *            Accepted mime types for this port
	 */
	private void addOutputWithMime(String portName, int portDepth, List<String> mimeTypes) {
		ActivityOutputPort outputPort = getEdits().createActivityOutputPort(portName, portDepth, portDepth);
		outputPorts.add(outputPort);
		addMimeTypes(outputPort, mimeTypes);
	}

	@Override
	public void configure(ExternalToolActivityConfigurationBean bean) throws ActivityConfigurationException {
		this.configurationBean = bean;

		try {
			mydesc = bean.getUseCaseDescription();

			inputPorts.clear();
			outputPorts.clear();

			if (mydesc != null) {

			// loop through all script inputs and add them as taverna activity
			// input ports
			for (Map.Entry<String, ScriptInput> cur : mydesc.getInputs().entrySet()) {
				ScriptInputUser scriptInputUser = (ScriptInputUser) cur.getValue();
				// if the input port is a list, depth is 1 otherwise it is a
				// single element, therefore depth 0
				// if the input port is binary, we would like byte arrays,
				// otherwise we require strings
				addInputWithMime(cur.getKey(), scriptInputUser.isList() ? 1 : 0, cur.getValue().isBinary() ? byte[].class : String.class, scriptInputUser.getMime());

			}
			// loop through all script outputs and add them to taverna
			for (Map.Entry<String, ScriptOutput> cur : mydesc.getOutputs().entrySet()) {
				addOutputWithMime(cur.getKey(), 0, cur.getValue().getMime());
			}
			}

			if (mydesc.isIncludeStdIn()) {
				addInputWithMime(STDIN, 0, byte[].class, null);
			}
			if (mydesc.isIncludeStdOut()) {
				addOutput(STDOUT, 0);
			}
			if (mydesc.isIncludeStdErr()) {
				addOutput(STDERR, 0);
			}
		} catch (Exception e) {
			throw new ActivityConfigurationException("Couldn't create ExternalTool Activity", e);
		}
	}

	@Override
	public ExternalToolActivityConfigurationBean getConfiguration() {
		if (configurationBean != null) {
			InvocationGroup invocationGroup = configurationBean.getInvocationGroup();
			if (invocationGroup == null) {
				if (configurationBean.getMechanism() != null) {
					configurationBean.convertMechanismToDetails();
				}
			} else {
				if (invocationGroup.getMechanism() != null) {
					invocationGroup.convertMechanismToDetails();
				}
			}
		}
		return configurationBean;
	}

	public ExternalToolActivityConfigurationBean getConfigurationNoConversion() {
		return configurationBean;
	}

	public InvocationMechanism recreateMechanism() {
		if (configurationBean.getInvocationGroup() != null) {
			if (configurationBean.getInvocationGroup().getMechanism() == null) {
				configurationBean.getInvocationGroup().convertDetailsToMechanism();
			}
			return configurationBean.getInvocationGroup().getMechanism();
		} else {
			if (configurationBean.getMechanism() == null) {
				configurationBean.convertDetailsToMechanism();
			}
			return configurationBean.getMechanism();
		}
	}

	@Override
	public void executeAsynch(final Map<String, T2Reference> data, final AsynchronousActivityCallback callback) {

		callback.requestRun(new Runnable() {

			public void run() {
				ReferenceService referenceService = callback.getContext().getReferenceService();
				UseCaseInvocation invoke = null;

				/**
				 * Note that retrying needs to be either done via Taverna's retry mechanism or as part of the specific invocation
				 */
				try {

					invoke = getInvocation(recreateMechanism(),
							configurationBean.getUseCaseDescription(), data, referenceService);
					if (invoke == null) {
						logger.error("Invoke is null");
						callback.fail("No invocation mechanism found");
					}
					String runId = callback.getContext()
							.getEntities(WorkflowRunIdEntity.class).get(0)
							.getWorkflowRunId();
					logger.info("Run id is " + runId);
					invoke.rememberRun(runId);

					invoke.setContext(callback.getContext());

					// look at every use dynamic case input
					for (String cur : invoke.getInputs()) {
						if (!cur.equals(STDIN)) {
							invoke.setInput(cur, referenceService,
									data.get(cur));
						}
					}

					if (mydesc.isIncludeStdIn() && (data.get(STDIN) != null)) {
						invoke.setStdIn(referenceService, data.get(STDIN));
					}

					// submit the use case to its invocation mechanism
					invoke.submit_generate_job(referenceService);

					// retrieve the result.
					Map<String, Object> downloads = invoke
							.submit_wait_fetch_results(referenceService);
					Map<String, T2Reference> result = new HashMap<String, T2Reference>();
					for (Map.Entry<String, Object> cur : downloads.entrySet()) {
						Object value = cur.getValue();

						// register the result value with taverna
						T2Reference reference = referenceService.register(
								value, 0, true, callback.getContext());

						// store the reference into the activity result
						// set
						result.put(cur.getKey(), reference);
					}
					callback.receiveResult(result, new int[0]);
				} catch (InvocationException e) {
					callback.fail(e.getMessage(), e);
				}
			}

		});

	}

	public void setInvocationCreators(List<InvocationCreator> invocationCreators) {
		this.invocationCreators = invocationCreators;
	}

	private UseCaseInvocation getInvocation(InvocationMechanism mechanism, UseCaseDescription description, Map<String, T2Reference> data, ReferenceService referenceService) {
		UseCaseInvocation result = null;
		InvocationCreator creator = null;
		for (InvocationCreator c : invocationCreators) {
			if (c.canHandle(mechanism.getType())) {
				creator = c;
				break;
			}
		}
		if (creator != null) {
			result = creator.convert(mechanism, description, data, referenceService);
		}
		return result;
	}

}
