package org.purl.wf4ever.robundle.manifest;

import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.purl.wf4ever.robundle.Bundle;
import org.purl.wf4ever.robundle.Bundles;
import org.purl.wf4ever.robundle.manifest.combine.CombineManifest;
import org.purl.wf4ever.robundle.manifest.odf.ODFManifest;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

@JsonPropertyOrder(value = { "@context", "id", "manifest", "createdOn",
		"createdBy", "createdOn", "authoredOn", "authoredBy", "history",
		"aggregates", "annotations", "@graph" })
public class Manifest {

	public abstract class FileTimeMixin {
		@JsonValue
		public abstract String toString();
	}

	public abstract class PathMixin {
		@JsonValue
		public abstract String toString();
	}

	private static Logger logger = Logger.getLogger(Manifest.class
			.getCanonicalName());

	private static final String MANIFEST_JSON = "manifest.json";

	private static final String META_INF = "/META-INF";

	private static final String MIMETYPE = "/mimetype";
	private static final String RO = "/.ro";
	private static URI ROOT = URI.create("/");

	public static FileTime now() {
		return FileTime.fromMillis(new GregorianCalendar().getTimeInMillis());
	}

	protected static Path withSlash(Path dir) {
		if (dir == null) {
			return null;
		}
		if (Files.isDirectory(dir)) {
			Path fname = dir.getFileName();
			if (fname == null) {
				return dir;
			}
			String fnameStr = fname.toString();
			if (fnameStr.endsWith("/")) {
				return dir;
			}
			return dir.resolveSibling(fnameStr + "/");
		}
		return dir;
	}

	private Map<URI, PathMetadata> aggregates = new LinkedHashMap<>();
	private List<PathAnnotation> annotations = new ArrayList<>();
	private List<Agent> authoredBy = new ArrayList<>();
	private FileTime authoredOn;
	private Bundle bundle;
	private Agent createdBy = null;
	private FileTime createdOn = now();
	private List<String> graph;
	private List<Path> history = new ArrayList<>();
	private URI id = URI.create("/");
	private List<Path> manifest = new ArrayList<>();

	public Manifest(Bundle bundle) {
		this.bundle = bundle;
	}

	public List<PathMetadata> getAggregates() {
		return new ArrayList<>(aggregates.values());
	}

	public PathMetadata getAggregation(Path file) {
		URI fileUri = file.toUri();
		return getAggregation(fileUri);
	}

	public PathMetadata getAggregation(URI uri) {
		uri = relativeToBundleRoot(uri);
		PathMetadata metadata = aggregates.get(uri);
		if (metadata == null) {
			metadata = new PathMetadata();
			if (!uri.isAbsolute() && uri.getFragment() == null) {
				Path path = Bundles.uriToBundlePath(bundle, uri);
				metadata.setFile(path);
				metadata.setMediatype(guessMediaType(path));
			} else {
				metadata.setUri(uri);
			}
			aggregates.put(uri, metadata);
		}
		return metadata;
	}

	public List<PathAnnotation> getAnnotations() {
		return annotations;
	}

	public List<Agent> getAuthoredBy() {
		return authoredBy;
	}

	public FileTime getAuthoredOn() {
		return authoredOn;
	}

	@JsonIgnore
	public URI getBaseURI() {
		return getBundle().getRoot().toUri();
	}

	@JsonIgnore
	public Bundle getBundle() {
		return bundle;
	}

	@JsonProperty(value = "@context")
	public List<Object> getContext() {
		ArrayList<Object> context = new ArrayList<>();
		// HashMap<Object, Object> map = new HashMap<>();
		// map.put("@base", getBaseURI());
		// context.add(map);
		context.add(URI.create("https://w3id.org/bundle/context"));
		return context;
	}

	public Agent getCreatedBy() {
		return createdBy;
	}

	public FileTime getCreatedOn() {
		return createdOn;
	}

	public List<String> getGraph() {
		return graph;
	}

	public List<Path> getHistory() {
		return history;
	}

	public URI getId() {
		return id;
	}

	public List<Path> getManifest() {
		return manifest;
	}

	/**
	 * Guess media type based on extension
	 * 
	 * @see http://wf4ever.github.io/ro/bundle/#media-types
	 * 
	 * @param file
	 *            A Path to a file
	 * @return media-type, e.g. <code>application/xml</code> or
	 *         <code>text/plain; charset="utf-8"</code>
	 */
	public String guessMediaType(Path file) {
		if (file.getFileName() == null) {
			return null;
		}
		String filename = file.getFileName().toString()
				.toLowerCase(Locale.ENGLISH);
		if (filename.endsWith(".txt")) {
			return "text/plain; charset=\"utf-8\"";
		}
		if (filename.endsWith(".ttl")) {
			return "text/turtle; charset=\"utf-8\"";
		}
		if (filename.endsWith(".rdf") || filename.endsWith(".owl")) {
			return "application/rdf+xml";
		}
		if (filename.endsWith(".json")) {
			return "application/json";
		}
		if (filename.endsWith(".jsonld")) {
			return "application/ld+json";
		}
		if (filename.endsWith(".xml")) {
			return "application/xml";
		}

		// A few extra, common ones

		if (filename.endsWith(".png")) {
			return "image/png";
		}
		if (filename.endsWith(".svg")) {
			return "image/svg+xml";
		}
		if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
			return "image/jpeg";
		}
		if (filename.endsWith(".pdf")) {
			return "application/pdf";
		}
		return "application/octet-stream";
	}

	public void populateFromBundle() throws IOException {
		final Set<Path> potentiallyEmptyFolders = new LinkedHashSet<>();

		final Set<URI> existingAggregationsToPrune = new HashSet<>(
				aggregates.keySet());

		Files.walkFileTree(bundle.getRoot(), new SimpleFileVisitor<Path>() {
			@Override
			public FileVisitResult postVisitDirectory(Path dir, IOException exc)
					throws IOException {
				super.postVisitDirectory(dir, exc);
				if (potentiallyEmptyFolders.remove(dir)) {
					URI uri = relativeToBundleRoot(dir.toUri());
					existingAggregationsToPrune.remove(uri);
					PathMetadata metadata = aggregates.get(uri);
					if (metadata == null) {
						metadata = new PathMetadata();
						aggregates.put(uri, metadata);
					}
					metadata.setFile(withSlash(dir));
					metadata.setFolder(withSlash(dir.getParent()));
					metadata.setProxy();
					metadata.setCreatedOn(Files.getLastModifiedTime(dir));
					potentiallyEmptyFolders.remove(withSlash(dir.getParent()));
					return FileVisitResult.CONTINUE;
				}
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult preVisitDirectory(Path dir,
					BasicFileAttributes attrs) throws IOException {
				if (dir.startsWith(RO) || dir.startsWith(META_INF)) {
					return FileVisitResult.SKIP_SUBTREE;
				}
				potentiallyEmptyFolders.add(withSlash(dir));
				potentiallyEmptyFolders.remove(withSlash(dir.getParent()));
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult visitFile(Path file,
					BasicFileAttributes attrs) throws IOException {
				potentiallyEmptyFolders.remove(withSlash(file.getParent()));
				if (file.startsWith(MIMETYPE)) {
					return FileVisitResult.CONTINUE;
				}
				if (manifest.contains(file)) {
					// Don't aggregate the manifests
					return FileVisitResult.CONTINUE;
				}
				// super.visitFile(file, attrs);
				URI uri = relativeToBundleRoot(file.toUri());
				existingAggregationsToPrune.remove(uri);
				PathMetadata metadata = aggregates.get(uri);
				if (metadata == null) {
					metadata = new PathMetadata();
					aggregates.put(uri, metadata);
				}
				metadata.setFile(file);
				if (metadata.getMediatype() == null) {
					// Don't override if already set
					metadata.setMediatype(guessMediaType(file));
				}
				metadata.setFolder(withSlash(file.getParent()));
				metadata.setProxy();
				metadata.setCreatedOn(Files.getLastModifiedTime(file));
				potentiallyEmptyFolders.remove(file.getParent());
				return FileVisitResult.CONTINUE;
			}
		});
		for (URI preExisting : existingAggregationsToPrune) {
			PathMetadata meta = aggregates.get(preExisting);
			if (meta.getFile() != null) {
				// Don't remove 'virtual' resources, only aggregations
				// that went to files
				aggregates.remove(preExisting);
			}
		}
	}

	public URI relativeToBundleRoot(URI uri) {
		uri = ROOT.resolve(bundle.getRoot().toUri().relativize(uri));
		return uri;
	}

	public void setAggregates(List<PathMetadata> aggregates) {
		this.aggregates.clear();

		for (PathMetadata meta : aggregates) {
			URI uri = null;
			if (meta.getFile() != null) {
				uri = relativeToBundleRoot(meta.getFile().toUri());
			} else if (meta.getUri() != null) {
				uri = relativeToBundleRoot(meta.getUri());
			} else {
				uri = relativeToBundleRoot(meta.getProxy());
			}
			if (uri == null) {
				logger.warning("Unknown URI for aggregation " + meta);
				continue;
			}
			this.aggregates.put(uri, meta);
		}

	}

	public void setAnnotations(List<PathAnnotation> annotations) {
		this.annotations = annotations;
	}

	public void setAuthoredBy(List<Agent> authoredBy) {
		if (authoredBy == null) {
			throw new NullPointerException("authoredBy can't be null");
		}
		this.authoredBy = authoredBy;
	}

	public void setAuthoredOn(FileTime authoredOn) {
		this.authoredOn = authoredOn;
	}

	public void setBundle(Bundle bundle) {
		this.bundle = bundle;
	}

	public void setCreatedBy(Agent createdBy) {
		this.createdBy = createdBy;
	}

	public void setCreatedOn(FileTime createdOn) {
		this.createdOn = createdOn;
	}

	public void setGraph(List<String> graph) {
		this.graph = graph;
	}

	public void setHistory(List<Path> history) {
		if (history == null) {
			throw new NullPointerException("history can't be null");
		}
		this.history = history;
	}

	public void setId(URI id) {
		this.id = id;
	}

	public void setManifest(List<Path> manifest) {
		this.manifest = manifest;
	}

	public void writeAsCombineManifest() throws IOException {
		new CombineManifest(this).createManifestXML();
	}

	/**
	 * Write as an RO Bundle JSON-LD manifest
	 * 
	 * @return The path of the written manifest (e.g. ".ro/manifest.json")
	 * @throws IOException
	 */
	public Path writeAsJsonLD() throws IOException {
		Path jsonld = bundle.getFileSystem().getPath(RO, MANIFEST_JSON);
		Files.createDirectories(jsonld.getParent());
		// Files.createFile(jsonld);
		if (!getManifest().contains(jsonld)) {
			getManifest().add(0, jsonld);
		}
		ObjectMapper om = new ObjectMapper();
		om.addMixInAnnotations(Path.class, PathMixin.class);
		om.addMixInAnnotations(FileTime.class, FileTimeMixin.class);
		om.enable(SerializationFeature.INDENT_OUTPUT);
		om.disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
		om.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
		om.disable(SerializationFeature.WRITE_NULL_MAP_VALUES);

		om.setSerializationInclusion(Include.NON_NULL);
		try (Writer w = Files
				.newBufferedWriter(jsonld, Charset.forName("UTF-8"),
						StandardOpenOption.WRITE,
						StandardOpenOption.TRUNCATE_EXISTING,
						StandardOpenOption.CREATE)) {
			om.writeValue(w, this);
		}
		return jsonld;
	}

	/**
	 * Write as a ODF manifest.xml
	 * 
	 * @see http
	 *      ://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part3.
	 *      html#__RefHeading__752807_826425813
	 * @return The path of the written manifest (e.g. "META-INF/manifest.xml")
	 * @throws IOException
	 */
	public Path writeAsODFManifest() throws IOException {
		return new ODFManifest(this).createManifestXML();
	}
}
