package org.apache.taverna.robundle.manifest;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import static org.apache.jena.ontology.OntModelSpec.OWL_DL_MEM_RULE_INF;
import static org.apache.jena.rdf.model.ModelFactory.createOntologyModel;
import static org.apache.taverna.robundle.utils.PathHelper.relativizeFromBase;
import static org.apache.taverna.robundle.utils.RDFUtils.literalAsFileTime;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.riot.RiotException;
import org.apache.taverna.robundle.Bundles;

import org.apache.taverna.ro.vocabs.Foaf;
import org.apache.taverna.ro.vocabs.Prov_o;
import org.apache.taverna.ro.vocabs.RO;
import org.apache.taverna.ro.vocabs.ROEvo;
import org.apache.taverna.ro.vocabs.Roterms;
import org.apache.taverna.ro.vocabs.Wf4ever;
import org.apache.taverna.ro.vocabs.Wfdesc;
import org.apache.taverna.ro.vocabs.Wfprov;

import org.apache.jena.ontology.DatatypeProperty;
import org.apache.jena.ontology.Individual;
import org.apache.jena.ontology.ObjectProperty;
import org.apache.jena.ontology.OntClass;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.ontology.OntResource;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.util.iterator.ExtendedIterator;

public class RDFToManifest {
	public static class ClosableIterable<T> implements AutoCloseable,
			Iterable<T> {

		private ExtendedIterator<T> iterator;

		public ClosableIterable(ExtendedIterator<T> iterator) {
			this.iterator = iterator;
		}

		@Override
		public void close() {
			iterator.close();
		}

		@Override
		public ExtendedIterator<T> iterator() {
			return iterator;
		}
	}

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

	private static <T> ClosableIterable<T> iterate(ExtendedIterator<T> iterator) {
		return new ClosableIterable<T>(iterator);
	}

	protected static Model jsonLdAsJenaModel(InputStream jsonIn, URI base)
			throws IOException, RiotException {
		Model model = ModelFactory.createDefaultModel();

		ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
		try {
			// TAVERNA-971: set context classloader so jarcache.json is consulted
			// even through OSGi
			Thread.currentThread().setContextClassLoader(RDFToManifest.class.getClassLoader());

			// Now we can parse the JSON-LD without network access
			RDFDataMgr.read(model, jsonIn, base.toASCIIString(), Lang.JSONLD);
		} finally {
			// Restore old context class loader (if any)
			Thread.currentThread().setContextClassLoader(oldCl);
		}
		return model;
	}

	protected static URI makeBaseURI() throws URISyntaxException {
		return new URI("app", UUID.randomUUID().toString(), "/", (String) null);
	}

	private Individual findRO(OntModel model, URI base) {
		try (ClosableIterable<? extends OntResource> instances = iterate(aggregation
				.listInstances())) {
			for (OntResource o : instances)
				// System.out.println("Woo " + o);
				return o.asIndividual();
		}
		// Fallback - resolve as "/"
		// TODO: Ensure it's an Aggregation?
		return model.getIndividual(base.toString());
	}

	private List<Agent> getAgents(URI base, Individual in,
			ObjectProperty property) {
		List<Agent> creators = new ArrayList<>();
		for (Individual agent : listObjectProperties(in, property)) {
			Agent a = new Agent();

			// Check for any ORCIDs, note that "orcid" is mapped as
			// prov:alternateOf in our modified bundle.jsonld
			for (Individual alternate : listObjectProperties(agent, alternateOf)) {
				if (alternate.isURIResource() && (
						alternate.getURI().startsWith("https://orcid.org/") ||
						alternate.getURI().startsWith("http://orcid.org/"))) {
					// TODO: Check against https://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier
					a.setOrcid(URI.create(alternate.getURI()));
					break;
				}
			}
			if (agent.isURIResource()) {
				URI agentURI = relativizeFromBase(agent.getURI(), base);
				if ("orcid.org".equals(agentURI.getHost()) && a.getOrcid() == null) {
					a.setOrcid(agentURI);
				} else {
					a.setUri(agentURI);
				}
			}

			RDFNode name = agent.getPropertyValue(foafName);
			if (name != null && name.isLiteral())
				a.setName(name.asLiteral().getLexicalForm());
			creators.add(a);
		}
		return creators;
	}

	protected OntModel getOntModel() {
		OntModel ontModel = createOntologyModel(OWL_DL_MEM_RULE_INF);
		ontModel.setNsPrefix("foaf", Foaf.);
		ontModel.setNsPrefix("prov", PROV);
		ontModel.setNsPrefix("ore", ORE);
		ontModel.setNsPrefix("pav", PAV);
		ontModel.setNsPrefix("dct", DCT);
		// ontModel.getDocumentManager().loadImports(foaf.getOntModel());
		return ontModel;
	}

	private Set<Individual> listObjectProperties(OntResource ontResource,
			ObjectProperty prop) {
		LinkedHashSet<Individual> results = new LinkedHashSet<>();
		try (ClosableIterable<RDFNode> props = iterate(ontResource
				.listPropertyValues(prop))) {
			for (RDFNode node : props) {
				if (!node.isResource() || !node.canAs(Individual.class))
					continue;
				results.add(node.as(Individual.class));
			}
		}
		return results;
	}

	public void readTo(InputStream manifestResourceAsStream, Manifest manifest,
			URI manifestResourceBaseURI) throws IOException, RiotException {
		OntModel model = new RDFToManifest().getOntModel();
		model.add(jsonLdAsJenaModel(manifestResourceAsStream,
				manifestResourceBaseURI));

		URI root = manifestResourceBaseURI.resolve("/");
		Individual ro = findRO(model, root);
		if (ro == null)
			throw new IOException("root ResearchObject not found - "
					+ "Not a valid RO Bundle manifest");

		// isDescribedBy URI
		for (Individual manifestResource : listObjectProperties(ro,
				isDescribedBy)) {
			String uriStr = manifestResource.getURI();
			if (uriStr == null) {
				logger.warning("Skipping manifest without URI: "
						+ manifestResource);
				continue;
			}
			// URI relative = relativizeFromBase(uriStr, root);
			Path path = manifest.getBundle().getFileSystem().provider()
					.getPath(URI.create(uriStr));
			manifest.getManifest().add(path);
		}

		// createdBy
		List<Agent> creators = getAgents(root, ro, createdBy);
		if (!creators.isEmpty()) {
			manifest.setCreatedBy(creators.get(0));
			if (creators.size() > 1) {
				logger.warning("Ignoring additional createdBy agents");
			}
		}

		// createdOn
		RDFNode created = ro.getPropertyValue(createdOn);
		manifest.setCreatedOn(literalAsFileTime(created));

		// history
		List<Path> history = new ArrayList<Path> ();
		for (Individual histItem : listObjectProperties (ro, hasProvenance)) {
			history.add(Bundles.uriToBundlePath(manifest.getBundle(), relativizeFromBase(histItem.getURI(), root)));
		}
		manifest.setHistory(history);

		// authoredBy
		List<Agent> authors = getAgents(root, ro, authoredBy);
		if (!authors.isEmpty()) {
			manifest.setAuthoredBy(authors);
		}

		// authoredOn
		RDFNode authored = ro.getPropertyValue(authoredOn);
		manifest.setAuthoredOn(literalAsFileTime(authored));

		// retrievedFrom
		RDFNode retrievedNode = ro.getPropertyValue(retrievedFrom);
		if (retrievedNode != null) {
    		try {
    			manifest.setRetrievedFrom(new URI(retrievedNode.asResource().getURI()));
    		} catch (URISyntaxException ex) {
    			logger.log(Level.WARNING, "Error creating URI for retrievedFrom: " +
    					retrievedNode.asResource().getURI(), ex);
    		}
		}

		// retrievedBy
		List<Agent> retrievers = getAgents(root, ro, retrievedBy);
		if (!retrievers.isEmpty()) {
			manifest.setRetrievedBy(retrievers.get(0));
			if (retrievers.size() > 1) {
				logger.warning("Ignoring additional retrievedBy agents");
			}
		}

		// retrievedOn
		RDFNode retrieved = ro.getPropertyValue(retrievedOn);
		manifest.setRetrievedOn(literalAsFileTime(retrieved));

		// conformsTo
		for (Individual standard : listObjectProperties(ro,
				conformsTo)) {
			if (standard.isURIResource()) {
				URI uri;
				try {
					uri = new URI(standard.getURI());
				} catch (URISyntaxException ex) {
					logger.log(Level.WARNING, "Invalid URI for conformsTo: " +
					           standard, ex);
					continue;
				}
				if (! manifest.getConformsTo().contains(uri)) {
					manifest.getConformsTo().add(uri);
				}
			}
		}

		// Aggregates
		for (Individual aggrResource : listObjectProperties(ro, aggregates)) {
			String uriStr = aggrResource.getURI();
			// PathMetadata meta = new PathMetadata();
			if (uriStr == null) {
				logger.warning("Skipping aggregation without URI: "
						+ aggrResource);
				continue;
			}

			PathMetadata meta = manifest.getAggregation(relativizeFromBase(
					uriStr, root));

			Set<Individual> proxies = listObjectProperties(aggrResource,
					hasProxy);
			if (proxies.isEmpty()) {
				// FIXME: Jena does not follow OWL properties paths from hasProxy
				proxies = listObjectProperties(aggrResource, bundledAs);
			}
			if (!proxies.isEmpty()) {
				// Should really only be one anyway
				Individual proxy = proxies.iterator().next();

				String proxyUri = null;
				if (proxy.getURI() != null) {
					proxyUri = proxy.getURI();
				} else if (proxy.getSameAs() != null) {
					proxyUri = proxy.getSameAs().getURI();
				}

				Proxy proxyInManifest = meta.getOrCreateBundledAs();
				if (proxyUri != null) {
					proxyInManifest.setURI(relativizeFromBase(proxyUri, root));
				}

				RDFNode eName = proxy.getPropertyValue(entryName);
				if (eName != null && eName.isLiteral()) {
					proxyInManifest.setFilename(eName.asLiteral().getString());;
				}
				RDFNode folder = proxy.getPropertyValue(inFolder);
				if (folder != null && folder.isURIResource()) {
					URI folderUri = URI.create(folder.asResource().getURI());
					if (! folderUri.resolve("/").equals(manifest.getBaseURI())) {
						logger.warning("Invalid bundledAs folder, outside base URI of RO: " + folderUri);
						continue;
					}
					Path folderPath = Paths.get(folderUri);
					// Note: folder need NOT exist in zip file, so we don't need to do
					// Files.createDirectories(folderPath);
					proxyInManifest.setFolder(folderPath);
				}

			}

			// createdBy
			creators = getAgents(root, aggrResource, createdBy);
			if (!creators.isEmpty()) {
				meta.setCreatedBy(creators.get(0));
				if (creators.size() > 1) {
					logger.warning("Ignoring additional createdBy agents for "
							+ meta);
				}
			}

			// createdOn
			meta.setCreatedOn(literalAsFileTime(aggrResource
					.getPropertyValue(createdOn)));

			// retrievedFrom
			RDFNode retrievedAggrNode = aggrResource.getPropertyValue(retrievedFrom);
			if (retrievedAggrNode != null) {
    			try {
    				meta.setRetrievedFrom(new URI(retrievedAggrNode.asResource().getURI()));
    			} catch (URISyntaxException ex) {
    				logger.log(Level.WARNING, "Error creating URI for retrievedFrom: " +
    						retrievedAggrNode.asResource().getURI(), ex);
    			}
			}

			// retrievedBy
			List<Agent> retrieversAggr = getAgents(root, aggrResource, retrievedBy);
			if (!retrieversAggr.isEmpty()) {
				meta.setRetrievedBy(retrieversAggr.get(0));
				if (retrieversAggr.size() > 1) {
					logger.warning("Ignoring additional retrievedBy agents for "
							+ meta);
				}
			}

			// retrievedOn
			RDFNode retrievedAggr = aggrResource.getPropertyValue(retrievedOn);
			meta.setRetrievedOn(literalAsFileTime(retrievedAggr));

			// conformsTo
			for (Individual standard : listObjectProperties(aggrResource,
					conformsTo)) {
				if (standard.getURI() != null) {
					meta.setConformsTo(relativizeFromBase(standard.getURI(),
							root));
				}
			}

			// format
			RDFNode mediaType = aggrResource.getPropertyValue(format);
			if (mediaType != null && mediaType.isLiteral()) {
				meta.setMediatype(mediaType.asLiteral().getLexicalForm());
			}
		}

		for (Individual ann : listObjectProperties(ro, hasAnnotation)) {
			/*
			 * Normally just one body per annotation, but just in case we'll
			 * iterate and split them out (as our PathAnnotation can only keep a
			 * single setContent() at a time)
			 */
			for (Individual body : listObjectProperties(
					model.getOntResource(ann), hasBody)) {
				if (! body.isURIResource()) {
					logger.warning("Can't find annotation body for anonymous "
							+ body);
					continue;
				}
				PathAnnotation pathAnn = new PathAnnotation();
				pathAnn.setContent(relativizeFromBase(body.getURI(), root));

				if (ann.getURI() != null)
					pathAnn.setUri(relativizeFromBase(ann.getURI(), root));
				else if (ann.getSameAs() != null
						&& ann.getSameAs().getURI() != null)
					pathAnn.setUri(relativizeFromBase(ann.getSameAs().getURI(),
							root));

				// Handle multiple about/hasTarget
				for (Individual target : listObjectProperties(ann, hasTarget))
					if (target.getURI() != null)
						pathAnn.getAboutList().add(
								relativizeFromBase(target.getURI(), root));
				manifest.getAnnotations().add(pathAnn);
			}
		}
	}
}
