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

import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
import static javax.ws.rs.core.Response.created;
import static javax.ws.rs.core.Response.noContent;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.seeOther;
import static javax.ws.rs.core.Response.status;
import static org.apache.commons.logging.LogFactory.getLog;
import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
import static org.taverna.server.master.api.ContentTypes.DIRECTORY_VARIANTS;
import static org.taverna.server.master.api.ContentTypes.INITIAL_FILE_VARIANTS;
import static org.taverna.server.master.common.Roles.SELF;
import static org.taverna.server.master.common.Roles.USER;
import static org.taverna.server.master.common.Uri.secure;
import static org.taverna.server.master.utils.RestUtils.opt;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Variant;
import javax.xml.ws.Holder;

import org.apache.commons.logging.Log;
import org.springframework.beans.factory.annotation.Required;
import org.taverna.server.master.api.DirectoryBean;
import org.taverna.server.master.exceptions.FilesystemAccessException;
import org.taverna.server.master.exceptions.NoDirectoryEntryException;
import org.taverna.server.master.exceptions.NoUpdateException;
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.rest.DirectoryContents;
import org.taverna.server.master.rest.FileSegment;
import org.taverna.server.master.rest.MakeOrUpdateDirEntry;
import org.taverna.server.master.rest.MakeOrUpdateDirEntry.MakeDirectory;
import org.taverna.server.master.rest.TavernaServerDirectoryREST;
import org.taverna.server.master.utils.FilenameUtils;
import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
import org.taverna.server.master.utils.InvocationCounter.CallCounted;

/**
 * RESTful access to the filesystem.
 * 
 * @author Donal Fellows
 */
class DirectoryREST implements TavernaServerDirectoryREST, DirectoryBean {
	private Log log = getLog("Taverna.Server.Webapp");
	private TavernaServerSupport support;
	private TavernaRun run;
	private FilenameUtils fileUtils;

	@Override
	public void setSupport(TavernaServerSupport support) {
		this.support = support;
	}

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

	@Override
	public DirectoryREST connect(TavernaRun run) {
		this.run = run;
		return this;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed({ USER, SELF })
	public Response destroyDirectoryEntry(List<PathSegment> path)
			throws NoUpdateException, FilesystemAccessException,
			NoDirectoryEntryException {
		support.permitUpdate(run);
		fileUtils.getDirEntry(run, path).destroy();
		return noContent().build();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed({ USER, SELF })
	public DirectoryContents getDescription(UriInfo ui)
			throws FilesystemAccessException {
		return new DirectoryContents(ui, run.getWorkingDirectory()
				.getContents());
	}

	@Override
	@CallCounted
	public Response options(List<PathSegment> path) {
		return opt("PUT", "POST", "DELETE");
	}

	/*
	 * // Nasty! This can have several different responses...
	 * 
	 * @Override @CallCounted private Response
	 * getDirectoryOrFileContents(List<PathSegment> path, UriInfo ui, Request
	 * req) throws FilesystemAccessException, NoDirectoryEntryException {
	 * 
	 * DirectoryEntry de = fileUtils.getDirEntry(run, path);
	 * 
	 * // How did the user want the result?
	 * 
	 * List<Variant> variants = getVariants(de); Variant v =
	 * req.selectVariant(variants); if (v == null) return
	 * notAcceptable(variants).type(TEXT_PLAIN)
	 * .entity("Do not know what type of response to produce.") .build();
	 * 
	 * // Produce the content to deliver up
	 * 
	 * Object result; if
	 * (v.getMediaType().equals(APPLICATION_OCTET_STREAM_TYPE))
	 * 
	 * // Only for files...
	 * 
	 * result = de; else if (v.getMediaType().equals(APPLICATION_ZIP_TYPE))
	 * 
	 * // Only for directories...
	 * 
	 * result = ((Directory) de).getContentsAsZip(); else
	 * 
	 * // Only for directories... // XML or JSON; let CXF pick what to do
	 * 
	 * result = new DirectoryContents(ui, ((Directory) de).getContents());
	 * return ok(result).type(v.getMediaType()).build();
	 * 
	 * }
	 */

	private boolean matchType(MediaType a, MediaType b) {
		if (log.isDebugEnabled())
			log.debug("comparing " + a.getType() + "/" + a.getSubtype()
					+ " and " + b.getType() + "/" + b.getSubtype());
		return (a.isWildcardType() || b.isWildcardType() || a.getType().equals(
				b.getType()))
				&& (a.isWildcardSubtype() || b.isWildcardSubtype() || a
						.getSubtype().equals(b.getSubtype()));
	}

	/**
	 * What are we willing to serve up a directory or file as?
	 * 
	 * @param de
	 *            The reference to the object to serve.
	 * @return The variants we can serve it as.
	 * @throws FilesystemAccessException
	 *             If we fail to read data necessary to detection of its media
	 *             type.
	 */
	private List<Variant> getVariants(DirectoryEntry de)
			throws FilesystemAccessException {
		if (de instanceof Directory)
			return DIRECTORY_VARIANTS;
		else if (!(de instanceof File))
			throw new FilesystemAccessException("not a directory or file!");
		File f = (File) de;
		List<Variant> variants = new ArrayList<>(INITIAL_FILE_VARIANTS);
		String contentType = support.getEstimatedContentType(f);
		if (!contentType.equals(APPLICATION_OCTET_STREAM)) {
			String[] ct = contentType.split("/");
			variants.add(0,
					new Variant(new MediaType(ct[0], ct[1]), (String) null, null));
		}
		return variants;
	}

	/** How did the user want the result? */
	private MediaType pickType(HttpHeaders headers, DirectoryEntry de)
			throws FilesystemAccessException, NegotiationFailedException {
		List<Variant> variants = getVariants(de);
		// Manual content negotiation!!! Ugh!
		for (MediaType mt : headers.getAcceptableMediaTypes())
			for (Variant v : variants)
				if (matchType(mt, v.getMediaType()))
					return v.getMediaType();
		throw new NegotiationFailedException(
				"Do not know what type of response to produce.", variants);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed({ USER, SELF })
	public Response getDirectoryOrFileContents(List<PathSegment> path,
			UriInfo ui, HttpHeaders headers) throws FilesystemAccessException,
			NoDirectoryEntryException, NegotiationFailedException {
		DirectoryEntry de = fileUtils.getDirEntry(run, path);

		// How did the user want the result?
		MediaType wanted = pickType(headers, de);

		log.info("producing content of type " + wanted);
		// Produce the content to deliver up
		Object result;
		if (de instanceof File) {
			// Only for files...
			result = de;
			List<String> range = headers.getRequestHeader("Range");
			if (range != null && range.size() == 1)
				return new FileSegment((File) de, range.get(0))
						.toResponse(wanted);
		} else {
			// Only for directories...
			Directory d = (Directory) de;
			if (wanted.getType().equals(APPLICATION_ZIP_TYPE.getType())
					&& wanted.getSubtype().equals(
							APPLICATION_ZIP_TYPE.getSubtype()))
				result = d.getContentsAsZip();
			else
				// XML or JSON; let CXF pick what to do
				result = new DirectoryContents(ui, d.getContents());
		}
		return ok(result).type(wanted).build();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed({ USER, SELF })
	public Response makeDirectoryOrUpdateFile(List<PathSegment> parent,
			MakeOrUpdateDirEntry op, UriInfo ui) throws NoUpdateException,
			FilesystemAccessException, NoDirectoryEntryException {
		support.permitUpdate(run);
		DirectoryEntry container = fileUtils.getDirEntry(run, parent);
		if (!(container instanceof Directory))
			throw new FilesystemAccessException("You may not "
					+ ((op instanceof MakeDirectory) ? "make a subdirectory of"
							: "place a file in") + " a file.");
		if (op.name == null || op.name.length() == 0)
			throw new FilesystemAccessException("missing name attribute");
		Directory d = (Directory) container;
		UriBuilder ub = secure(ui).path("{name}");

		// Make a directory in the context directory

		if (op instanceof MakeDirectory) {
			Directory target = d.makeSubdirectory(support.getPrincipal(),
					op.name);
			return created(ub.build(target.getName())).build();
		}

		// Make or set the contents of a file

		File f = null;
		for (DirectoryEntry e : d.getContents()) {
			if (e.getName().equals(op.name)) {
				if (e instanceof Directory)
					throw new FilesystemAccessException(
							"You may not overwrite a directory with a file.");
				f = (File) e;
				break;
			}
		}
		if (f == null) {
			f = d.makeEmptyFile(support.getPrincipal(), op.name);
			f.setContents(op.contents);
			return created(ub.build(f.getName())).build();
		}
		f.setContents(op.contents);
		return seeOther(ub.build(f.getName())).build();
	}

	private File getFileForWrite(List<PathSegment> filePath,
			Holder<Boolean> isNew) throws FilesystemAccessException,
			NoDirectoryEntryException, NoUpdateException {
		support.permitUpdate(run);
		if (filePath == null || filePath.size() == 0)
			throw new FilesystemAccessException(
					"Cannot create a file that is not in a directory.");

		List<PathSegment> dirPath = new ArrayList<>(filePath);
		String name = dirPath.remove(dirPath.size() - 1).getPath();
		DirectoryEntry de = fileUtils.getDirEntry(run, dirPath);
		if (!(de instanceof Directory)) {
			throw new FilesystemAccessException(
					"Cannot create a file that is not in a directory.");
		}
		Directory d = (Directory) de;

		File f = null;
		isNew.value = false;
		for (DirectoryEntry e : d.getContents())
			if (e.getName().equals(name)) {
				if (e instanceof File) {
					f = (File) e;
					break;
				}
				throw new FilesystemAccessException(
						"Cannot create a file that is not in a directory.");
			}

		if (f == null) {
			f = d.makeEmptyFile(support.getPrincipal(), name);
			isNew.value = true;
		} else
			f.setContents(new byte[0]);
		return f;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed({ USER, SELF })
	public Response setFileContents(List<PathSegment> filePath,
			InputStream contents, UriInfo ui) throws NoDirectoryEntryException,
			NoUpdateException, FilesystemAccessException {
		Holder<Boolean> isNew = new Holder<>(true);
		support.copyStreamToFile(contents, getFileForWrite(filePath, isNew));

		if (isNew.value)
			return created(ui.getAbsolutePath()).build();
		else
			return noContent().build();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Response setFileContentsFromURL(List<PathSegment> filePath,
			List<URI> referenceList, UriInfo ui)
			throws NoDirectoryEntryException, NoUpdateException,
			FilesystemAccessException {
		support.permitUpdate(run);
		if (referenceList.isEmpty() || referenceList.size() > 1)
			return status(422).entity("URI list must have single URI in it")
					.build();
		URI uri = referenceList.get(0);
		try {
			uri.toURL();
		} catch (MalformedURLException e) {
			return status(422).entity("URI list must have value URL in it")
					.build();
		}
		Holder<Boolean> isNew = new Holder<>(true);
		File f = getFileForWrite(filePath, isNew);

		try {
			support.copyDataToFile(uri, f);
		} catch (MalformedURLException ex) {
			// Should not happen; called uri.toURL() successfully above
			throw new NoUpdateException("failed to parse URI", ex);
		} catch (IOException ex) {
			throw new FilesystemAccessException(
					"failed to transfer data from URI", ex);
		}

		if (isNew.value)
			return created(ui.getAbsolutePath()).build();
		else
			return noContent().build();
	}
}
