package de.csw.ontomaven;

import java.io.File;
import java.util.Optional;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;

import owl2prefuse.graph.OWLGraphConverter;
import prefuse.data.Graph;
import prefuse.data.io.DataIOException;
import prefuse.data.io.GraphMLWriter;

import org.apache.jena.ontology.OntModel;

import de.csw.ontomaven.util.Util;

/**
 * Creates a graphml file of the ontology. This file can be visualized
 * with any tool, which supports graphml files.
 * 
 * @goal CreateOntologyGraph
 * @phase site
 * @configurator include-project-dependencies
 * @requiresDependencyResolution compile+runtime
 */
public class CreateOntologyGraph extends AbstractMojo {
	
	/**
	 * Working directory, where owl files are stored. It should be
	 * a relative path in the maven project directory.
	 * 
	 * @parameter 	property="owlDirectory"
	 * 				default-value="owl"
	 * @required
	 */
	private String owlDirectory;
	
	/**
	 * Name of the ontology file, which should be in the working directory.
	 * It should be a name like "myOntology.owl".
	 *
	 * @parameter 	property="owlFileName"
	 * 				default-value="ontology.owl"
	 * @required
	 */
	private String owlFileName;
	
	/**
	 * The output directory for the graph files. There will be saved
	 * the graph file. It should be relative path.
	 * 
	 * @parameter property="graphDirectory"
	 *            default-value="site/graph"
	 */
	private String graphDirectory;
	
	/**
	 * The name of the produced graph file. It should be name like
	 * "myGraph.graphml"
	 * 
	 * @parameter property="graphFileName"
	 *            default-value="owlGraph.graphml"
	 */
	private String graphFileName;
	
	/**
	 * IRI of the aspect annotation property. All annotations which have
	 * this iri as annotation property value, will be classified as
	 * aspect annotations.
	 * 
	 * @parameter property="aspectsIRI"
	 * default-value="http://www.corporate-semantic-web.de/ontologies/aspect_owl#hasAspect"
	 */
	private String aspectsIRI;
	
	/**
	 * If the goal should apply the aspects on the ontology before it
	 * works with the ontology.
	 * 
	 * @parameter 	parameter="ifApplyAspects"
	 *				defaul-value="false"
	 */
	private boolean ifApplyAspects;
	
	/**
	 * Aspects given by the user. These aspects will be applied on
	 * the ontology, if they are contained in the ontology.
	 * 
	 * @parameter
	 */
	private String[] userAspects;

	/**
	 * If true it handles axioms with no aspects as if they would have every aspect, i.e. it will keep axioms that have no aspects.
	 *
	 * @parameter property="keepNonAspectAxioms"
	 * default-value="false"
	 */
	private boolean keepNonAspectAxioms;

	/**
	 * Executes the creation of the graph file.
	 */
	public void execute() throws MojoExecutionException {
		owlDirectory = "target/" + owlDirectory;
		graphDirectory = "target/" + graphDirectory;

		Log log = getLog();
		Util.printHead("Creating graph...", log);
		
		// Loading ontology
		OWLOntologyManager manager = Util.createManager();
		File owlFile = Util.resolveFile(new File(owlDirectory + File.separator + owlFileName));
		Optional<OWLOntology> oontology = Util.loadOntologyFile( manager, log, owlFile );
		if (!oontology.isPresent()) {
			log.warn("Could not load ontology " + owlFile.getAbsolutePath() );
			return;
		}
		OWLOntology ontology = oontology.get();


		// Applying aspects
		if(ifApplyAspects) {
			Util.applyAspects(manager, aspectsIRI, ontology, userAspects, log, keepNonAspectAxioms);
			ontology = manager.ontologies().findFirst().get();
		}
		
		
		// Converting the ontology into the Jena OntModel format because
		// the owl2prefuse library only works with OntModel ontologies
		OntModel ontologyAsOntModel = Util.owlOntologyToJenaModel(ontology, false,
				log);		
		
		// Loading ontology and building graph
		OWLGraphConverter graphConverter = new OWLGraphConverter(
				ontologyAsOntModel, false);
		Graph graph = graphConverter.getGraph();
		log.info("Ontology is converted to graph.");
		
		
		// Creating output directory, if not existing
		new File(graphDirectory).mkdirs();

		
		// Saving graph in GraphML format
		log.info("Writing graph into file...");
		File graphFile = new File(graphDirectory + File.separator
				+ graphFileName);
		try {
			new GraphMLWriter().writeGraph(graph, graphFile);
			log.info("Graph written in " + graphFile.getAbsolutePath());
		} catch (DataIOException e) {
			log.error("Cannot create graph file.", e);
		}
		
		Util.printTail(log);
	}
	
	
}