/*
 * Copyright 2020 ETSI
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package fr.mines_stetienne.ci.saref.managers.parsers;

import java.io.StringWriter;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.NodeIterator;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.vocabulary.DCTerms;
import org.apache.jena.vocabulary.DCTypes;
import org.apache.jena.vocabulary.OWL2;
import org.apache.jena.vocabulary.RDF;
import org.semanticweb.owlapi.formats.TurtleDocumentFormatFactory;
import org.semanticweb.owlapi.io.OWLOntologyDocumentSource;
import org.semanticweb.owlapi.io.OWLParserException;
import org.semanticweb.owlapi.model.OWLDocumentFormat;
import org.semanticweb.owlapi.model.OWLDocumentFormatFactory;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyLoaderConfiguration;

import fr.mines_stetienne.ci.saref.SAREF;
import fr.mines_stetienne.ci.saref.SAREFPipeline;
import fr.mines_stetienne.ci.saref.entities.SAREFExample;
import fr.mines_stetienne.ci.saref.entities.SAREFProject;
import fr.mines_stetienne.ci.saref.entities.SAREFRepository;
import fr.mines_stetienne.ci.saref.entities.SAREFVersion;
import fr.mines_stetienne.ci.saref.entities.SAREFVersionName;
import fr.mines_stetienne.ci.saref.managers.RepositoryManager;
import fr.mines_stetienne.ci.saref.managers.SourcesManager;

/**
 *
 * @author Maxime Lefrançois
 *
 */
public class SourceOntologyParser extends AbstractJenaModelOntologyParser {

	private final SourcesManager sourcesManager;

	public SourceOntologyParser(SAREFPipeline pipeline) {
		super(pipeline);
		this.sourcesManager = pipeline.getSourcesManager();
	}

	@Override
	public OWLDocumentFormatFactory getSupportedFormat() {
		return new TurtleDocumentFormatFactory();
	}

	@Override
	public OWLDocumentFormat parse(OWLOntologyDocumentSource source, OWLOntology ontology,
			OWLOntologyLoaderConfiguration config) {
		
		String iri = source.getDocumentIRI().toString();
		
		SAREFProject project = SAREF.extractProject(iri);
		if(project == null) {
			throw new OWLParserException("not a SAREF iri: " + iri);
		}
		
		RepositoryManager repositoryManager = sourcesManager.findRepositoryManager(project);
		if(repositoryManager == null ) {
			throw new OWLParserException("no repositoryManager for " + project);
		}
		
		SAREFVersionName versionName = SAREF.extractVersionName(iri);
		if(versionName == null) {
			throw new OWLParserException("no versionName for " + iri);
		}
		
		SAREFRepository repository = repositoryManager.getRepository();
		SAREFVersion version = repository.getVersion(versionName);
		if(version == null) {
			throw new OWLParserException("no known version for " + iri);
		}
		
		if(version.getIRI().equals(iri)) {
			return parse(source, ontology, config, version.getModel());
		}
		
		String exampleName = SAREF.extractExampleName(iri);
		if(exampleName == null) {
			throw new OWLParserException("not a SAREF version IRI or a SAREF example IRI " + iri);
		}
		
		SAREFExample example = version.getExamples().get(exampleName);
		if(example == null) {
			throw new OWLParserException("no known example for " + iri);
		}

		Model modelForExample = getModelForExample(example);
		return parse(source, ontology, config, modelForExample);
	}

	private Model getModelForExample(SAREFExample example) {
		Model model = ModelFactory.createDefaultModel();
		model.add(example.getModel());
		model.remove(example.getResource(), RDF.type, DCTypes.Dataset);
		model.add(example.getResource(), RDF.type, OWL2.Ontology);
		for (NodeIterator nit = model.listObjectsOfProperty(example.getResource(), DCTerms.conformsTo); nit
				.hasNext();) {
			RDFNode n = nit.next();
			if (!n.isURIResource()) {
				model.remove(example.getResource(), DCTerms.conformsTo, n.asResource());
			}
			model.remove(example.getResource(), DCTerms.conformsTo, n.asResource());
			model.add(example.getResource(), OWL2.imports, n.asResource());
		}
		
		StringWriter sw = new StringWriter();
		model.write(sw, "TTL");
		String s = sw.toString();
		
		return model;
	}

}
