/*
 * Copyright (C) 2010-2011 The University of Manchester
 * 
 * See the file "LICENSE" for license terms.
 */
package org.taverna.server.master;

import static eu.medsea.util.MimeUtil.getMimeType;
import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
import static javax.ws.rs.core.UriBuilder.fromUri;
import static org.apache.commons.logging.LogFactory.getLog;
import static org.taverna.server.master.common.Uri.secure;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.logging.Log;
import org.springframework.beans.factory.annotation.Required;
import org.taverna.server.master.exceptions.FilesystemAccessException;
import org.taverna.server.master.exceptions.NoDirectoryEntryException;
import org.taverna.server.master.interfaces.Directory;
import org.taverna.server.master.interfaces.DirectoryEntry;
import org.taverna.server.master.interfaces.File;
import org.taverna.server.master.interfaces.TavernaRun;
import org.taverna.server.master.interfaces.UriBuilderFactory;
import org.taverna.server.master.utils.FilenameUtils;
import org.taverna.server.port_description.AbsentValue;
import org.taverna.server.port_description.AbstractPortDescription;
import org.taverna.server.port_description.AbstractValue;
import org.taverna.server.port_description.ErrorValue;
import org.taverna.server.port_description.InputDescription;
import org.taverna.server.port_description.InputDescription.InputPort;
import org.taverna.server.port_description.LeafValue;
import org.taverna.server.port_description.ListValue;
import org.taverna.server.port_description.OutputDescription;
import org.taverna.server.port_description.OutputDescription.OutputPort;

import uk.org.taverna.scufl2.api.container.WorkflowBundle;
import uk.org.taverna.scufl2.api.core.Workflow;
import uk.org.taverna.scufl2.api.port.InputWorkflowPort;
import uk.org.taverna.scufl2.api.port.OutputWorkflowPort;

/**
 * A class that is used to build descriptions of the contents of a workflow
 * run's filesystem.
 * 
 * @author Donal Fellows
 */
public class ContentsDescriptorBuilder {
	private Log log = getLog("Taverna.Server.Webapp");
	private FilenameUtils fileUtils;
	private UriBuilderFactory uriBuilderFactory;

	@Required
	public void setUriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
		this.uriBuilderFactory = uriBuilderFactory;
	}

	@Required
	public void setFileUtils(FilenameUtils fileUtils) {
		this.fileUtils = fileUtils;
	}

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

	private Workflow fillInFromWorkflow(TavernaRun run, UriBuilder ub,
			AbstractPortDescription portDesc) throws IOException {
		WorkflowBundle bundle = run.getWorkflow().getScufl2Workflow();
		bundle.getMainWorkflow().getInputPorts();
		portDesc.fillInBaseData(bundle.getMainWorkflow()
				.getWorkflowIdentifier().toString(), run.getId(), ub.build());
		return bundle.getMainWorkflow();
	}

	/**
	 * Computes the depth of value in a descriptor.
	 * 
	 * @param value
	 *            The value description to characterise.
	 * @return Its depth (i.e., the depth of the port outputting the value) or
	 *         <tt>null</tt> if that is impossible to determine.
	 */
	private Integer computeDepth(AbstractValue value) {
		if (value instanceof ListValue) {
			int mv = 1;
			for (AbstractValue v : ((ListValue) value).contents) {
				Integer d = computeDepth(v);
				if (d != null && mv <= d)
					mv = d + 1;
			}
			return mv;
		} else if (value instanceof LeafValue || value instanceof ErrorValue)
			return 0;
		else
			return null;
	}

	/**
	 * Build a description of a leaf value.
	 * 
	 * @param file
	 *            The file representing the value.
	 * @return A value descriptor.
	 * @throws FilesystemAccessException
	 *             If anything goes wrong.
	 */
	private LeafValue constructLeafValue(File file)
			throws FilesystemAccessException {
		LeafValue v = new LeafValue();
		v.fileName = file.getFullName();
		v.byteLength = file.getSize();
		try {
			byte[] head = file.getContents(0, 1024);
			v.contentType = getMimeType(new ByteArrayInputStream(head));
		} catch (Exception e) {
			v.contentType = APPLICATION_OCTET_STREAM_TYPE.toString();
		}
		return v;
	}

	/**
	 * Build a description of an error value.
	 * 
	 * @param file
	 *            The file representing the error.
	 * @return A value descriptor.
	 * @throws FilesystemAccessException
	 *             If anything goes wrong.
	 */
	private ErrorValue constructErrorValue(File file)
			throws FilesystemAccessException {
		ErrorValue v = new ErrorValue();
		v.fileName = file.getFullName();
		v.byteLength = file.getSize();
		return v;
	}

	/**
	 * Build a description of a list value.
	 * 
	 * @param dir
	 *            The directory representing the list.
	 * @param ub
	 *            The factory for URIs.
	 * @return A value descriptor.
	 * @throws FilesystemAccessException
	 *             If anything goes wrong.
	 */
	private ListValue constructListValue(Directory dir, UriBuilder ub)
			throws FilesystemAccessException {
		ListValue v = new ListValue();
		v.length = 0;
		Set<DirectoryEntry> contents = new HashSet<>(dir.getContents());
		Iterator<DirectoryEntry> it = contents.iterator();
		while (it.hasNext())
			if (!it.next().getName().matches("^[0-9]+([.].*)?$"))
				it.remove();
		for (int i = 1; !contents.isEmpty(); i++) {
			String exact = Integer.toString(i);
			AbstractValue subval = constructValue(contents, ub, exact);
			v.contents.add(subval);
			if (!(subval instanceof AbsentValue)) {
				v.length = i;
				String pfx = i + ".";
				for (DirectoryEntry de : contents)
					if (de.getName().equals(exact)
							|| de.getName().startsWith(pfx)) {
						contents.remove(de);
						break;
					}
			}
		}
		return v;
	}

	/**
	 * Build a value description.
	 * 
	 * @param parentContents
	 *            The contents of the parent directory.
	 * @param ub
	 *            The factory for URIs.
	 * @param name
	 *            The name of the value's file/directory representative.
	 * @return A value descriptor.
	 * @throws FilesystemAccessException
	 *             If anything goes wrong.
	 */
	private AbstractValue constructValue(
			Collection<DirectoryEntry> parentContents, UriBuilder ub,
			String name) throws FilesystemAccessException {
		String error = name + ".error";
		String prefix = name + ".";
		for (DirectoryEntry entry : parentContents) {
			AbstractValue av;
			if (entry.getName().equals(error) && entry instanceof File) {
				av = constructErrorValue((File) entry);
			} else if (!entry.getName().equals(name)
					&& !entry.getName().startsWith(prefix))
				continue;
			else if (entry instanceof File)
				av = constructLeafValue((File) entry);
			else
				av = constructListValue((Directory) entry, ub);
			String fullPath = entry.getFullName().replaceFirst("^/", "");
			av.href = ub.clone().path(fullPath).build();
			return av;
		}
		return new AbsentValue();
	}

	/**
	 * Construct a description of the outputs of a workflow run.
	 * 
	 * @param run
	 *            The workflow run whose outputs are to be described.
	 * @param ui
	 *            The origin for URIs.
	 * @return The description, which can be serialized to XML.
	 * @throws FilesystemAccessException
	 *             If something goes wrong reading the directories.
	 * @throws NoDirectoryEntryException
	 *             If something goes wrong reading the directories.
	 */
	public OutputDescription makeOutputDescriptor(TavernaRun run, UriInfo ui)
			throws FilesystemAccessException, NoDirectoryEntryException {
		OutputDescription descriptor = new OutputDescription();
		try {
			UriBuilder ub = getRunUriBuilder(run, ui);
			Workflow dataflow = fillInFromWorkflow(run, ub, descriptor);
			Collection<DirectoryEntry> outs = null;
			ub = ub.path("wd/{path}");
			for (OutputWorkflowPort output : dataflow.getOutputPorts()) {
				OutputPort p = descriptor.addPort(output.getName());
				if (run.getOutputBaclavaFile() == null) {
					if (outs == null)
						outs = fileUtils.getDirectory(run, "out").getContents();
					p.output = constructValue(outs, ub, p.name);
					p.depth = computeDepth(p.output);
				}
			}
		} catch (IOException e) {
			log.info("failure in conversion to .scufl2", e);
		}
		return descriptor;
	}

	private UriBuilder getRunUriBuilder(TavernaRun run, UriInfo ui) {
		if (ui == null)
			return secure(uriBuilderFactory.getRunUriBuilder(run));
		else
			return secure(fromUri(ui.getAbsolutePath().toString()
					.replaceAll("/(out|in)put/?$", "")));
	}

	/**
	 * Constructs input descriptions.
	 * 
	 * @param run
	 *            The run to build for.
	 * @param ui
	 *            The mechanism for building URIs.
	 * @return The description of the <i>expected</i> inputs of the run.
	 */
	public InputDescription makeInputDescriptor(TavernaRun run, UriInfo ui) {
		InputDescription desc = new InputDescription();
		try {
			UriBuilder ub = getRunUriBuilder(run, ui);
			Workflow workflow = fillInFromWorkflow(run, ub, desc);
			ub = ub.path("input/{name}");
			for (InputWorkflowPort port : workflow.getInputPorts()) {
				InputPort in = desc.addPort(port.getName());
				in.href = ub.build(in.name);
				try {
					in.depth = port.getDepth();
				} catch (NumberFormatException ex) {
					in.depth = null;
				}
			}
		} catch (IOException e) {
			log.info("failure in conversion to .scufl2", e);
		}
		return desc;
	}
}
