package fr.emse.gitlab.saref.jobs;

import org.apache.jena.query.Dataset;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ReadWrite;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.emse.gitlab.saref.Constants;

public class CheckConfig {

	static final String FIND_USED_UNDEFINED = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\r\n" + 
			"PREFIX rdfp: <https://w3id.org/rdfp/>\r\n" + 
			"PREFIX ex: <http://example.org/>\r\n" + 
			"\r\n" + 
			"SELECT ?term (SAMPLE(?v) AS ?version) WHERE {\r\n" + 
			"  ?term a rdfp:Resource ;\r\n" + 
			"    ex:isUsedBy ?v .\r\n" + 
			"  FILTER NOT EXISTS {\r\n" + 
			"  ?term rdfs:isDefinedBy ?ontology .\r\n" + 
			"  }\r\n" + 
			"} GROUP BY ?term \n"
			+ "ORDER BY ?term";

	static final String FIND_EXAMPLIFIED_UNDEFINED = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\r\n" + 
			"PREFIX rdfp: <https://w3id.org/rdfp/>\r\n" + 
			"PREFIX ex: <http://example.org/>\r\n" + 
			"\r\n" + 
			"SELECT ?term (SAMPLE(?e) AS ?example) WHERE {\r\n" + 
			"  ?term a rdfp:Resource ;\r\n" + 
			"    ex:hasExample ?e .\r\n" + 
			"  FILTER NOT EXISTS {\r\n" + 
			"  ?term rdfs:isDefinedBy ?ontology .\r\n" + 
			"  }\r\n" + 
			"} GROUP BY ?term \n"
			+ "ORDER BY ?term";

	static final String FIND_DEFINED_UNEXAMPLIFIED = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\r\n" + 
			"PREFIX rdfp: <https://w3id.org/rdfp/>\r\n" + 
			"PREFIX ex: <http://example.org/>\r\n" + 
			"\r\n" + 
			"SELECT ?term (SAMPLE(?o) AS ?ontology) WHERE {\r\n" + 
			"  ?term a rdfp:Resource ;\r\n" + 
			"    rdfs:isDefinedBy ?o .\r\n" + 
			"  FILTER NOT EXISTS {\r\n" + 
			"  ?term ex:hasExample ?e .\r\n" + 
			"  }\r\n" + 
			"} GROUP BY ?term \n"
			+ "ORDER BY ?term";

	public void doJob(Dataset dataset, boolean ignoreExamples) {
		dataset.begin(ReadWrite.READ);
		Model config = dataset.getNamedModel(Constants.CONFIG);

		// check which terms are used but not defined
		Logger logger = LoggerFactory.getLogger(Constants.LOGGER_BASE + "." + "Terms that are used but never defined");
		try (QueryExecution exec = QueryExecutionFactory.create(FIND_USED_UNDEFINED, config);) {
			for (ResultSet resultSet = exec.execSelect(); resultSet.hasNext();) {
				QuerySolution sol = resultSet.next();
				Resource term = sol.getResource("term");
				Resource version = sol.getResource("version");
				logger.warn(String.format("Term %s is never defined, but is used in version %s", term, version));
			}
		}
		
		if(!ignoreExamples) {
			
			// check which terms are exemplified but not defined
			logger = LoggerFactory.getLogger(Constants.LOGGER_BASE + "." + "Terms that have examples, but never defined");
			try (QueryExecution exec = QueryExecutionFactory.create(FIND_EXAMPLIFIED_UNDEFINED, config);) {
				for (ResultSet resultSet = exec.execSelect(); resultSet.hasNext();) {
					QuerySolution sol = resultSet.next();
					Resource term = sol.getResource("term");
					Resource example = sol.getResource("example");
					logger.warn(String.format("Term %s is never defined, but is used in example %s", term, example));
				}
			}
	
			// check which terms are defined but not exemplified
			logger = LoggerFactory.getLogger(Constants.LOGGER_BASE + "." + "Terms that are defined, but have no example");
			try (QueryExecution exec = QueryExecutionFactory.create(FIND_DEFINED_UNEXAMPLIFIED, config);) {
				for (ResultSet resultSet = exec.execSelect(); resultSet.hasNext();) {
					QuerySolution sol = resultSet.next();
					Resource term = sol.getResource("term");
					Resource ontology = sol.getResource("ontology");
					logger.warn(String.format("Term %s is defined in %s, but there is no example that use it.", term, ontology));
				}
			}
		}


		dataset.end();
	}
}
