package org.aksw.simba.qaldbench.rdf;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.openrdf.model.Model;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.LinkedHashModel;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.Rio;
import org.openrdf.sail.memory.MemoryStore;

import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.sparql.core.TriplePath;
import com.hp.hpl.jena.sparql.syntax.ElementPathBlock;
import com.hp.hpl.jena.sparql.syntax.ElementVisitorBase;
import com.hp.hpl.jena.sparql.syntax.ElementWalker;

import info.aduna.iteration.Iterations;

/**
 * RDFize annotaed QA dataset of 5000 questions
 * @author Saleem
 *
 */
public class QALDRDFizer {
	
	public static void main(String[] args) throws FileNotFoundException, IOException, RepositoryException, RDFHandlerException {
		// TODO Auto-generated method stub
		String annotatedFile = "annotated-dataset.txt" ;
		Model model = 	getRDFModel(annotatedFile);
		String outputFile = "output.ttl";
		 writeModel(model,outputFile);

	}

	public static Model getRDFModel(String annotatedFile) throws FileNotFoundException, IOException, RepositoryException {
		String res = "http://qald-gen.aksw.org/question#";
		 String vocab = "http://qald-gen.aksw.org/vocab#";
		 Repository	rep = new SailRepository(new MemoryStore());
			rep.initialize();
			ValueFactory	factory  = rep.getValueFactory();
			RepositoryConnection	conn = rep.getConnection();
		try(BufferedReader br = new BufferedReader(new FileReader(annotatedFile))) {
			 String line;
			 int question = 0 ;
			 br.readLine();
			    while ((line = br.readLine()) != null) {
			    	String prts [] = line.split("\t");
			    	URI instanceURI = factory.createURI(res+question);
			    	conn.add(instanceURI, factory.createURI(vocab,"text"), factory.createLiteral(prts[2]));
			    	conn.add(instanceURI, factory.createURI(vocab,"length"), factory.createLiteral(Integer.parseInt(prts[3])));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalEntities"), factory.createLiteral(Integer.parseInt(prts[4])));
			    	conn.add(instanceURI, factory.createURI(vocab,"entity1"), factory.createLiteral(prts[5]));
			    	Boolean bol = true ;
			    	if (Integer.parseInt(prts[6])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"isExplicitEntity1"), factory.createLiteral(bol));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalWordsEntity1"), factory.createLiteral(Integer.parseInt(prts[8])));
			    	conn.add(instanceURI, factory.createURI(vocab,"entity2"), factory.createLiteral(prts[9]));
			       	bol = true ;
			    	if (Integer.parseInt(prts[10])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"isExplicitEntity2"), factory.createLiteral(bol));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalWordsEntity2"), factory.createLiteral(Integer.parseInt(prts[12])));
			    	conn.add(instanceURI, factory.createURI(vocab,"avgEntitiesWords"), factory.createLiteral(Double.parseDouble((prts[13]))));
			    	
			    	conn.add(instanceURI, factory.createURI(vocab,"totalRelations"), factory.createLiteral(Integer.parseInt(prts[14])));
			    	conn.add(instanceURI, factory.createURI(vocab,"relation1"), factory.createLiteral(prts[15]));
			    	bol = true ; 	
			    	if (Integer.parseInt(prts[16])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"isExplicitRelation1"), factory.createLiteral(bol));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalWordsRelation1"), factory.createLiteral(Integer.parseInt(prts[18])));
			    	conn.add(instanceURI, factory.createURI(vocab,"relation2"), factory.createLiteral(prts[19]));
			    	bol = true ;
			    	if (Integer.parseInt(prts[20])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"isExplicitRelation2"), factory.createLiteral(bol));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalWordsRelation2"), factory.createLiteral(Integer.parseInt(prts[22])));
			    	conn.add(instanceURI, factory.createURI(vocab,"avgRelationsWords"), factory.createLiteral(Double.parseDouble((prts[23]))));
			    	
			    	conn.add(instanceURI, factory.createURI(vocab,"totalClasses"), factory.createLiteral(Integer.parseInt(prts[24])));
			    	conn.add(instanceURI, factory.createURI(vocab,"class1"), factory.createLiteral(prts[25]));
			    	bol = true ; 	
			    	if (Integer.parseInt(prts[26])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"isExplicitClass1"), factory.createLiteral(bol));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalWordsClass1"), factory.createLiteral(Integer.parseInt(prts[28])));
			    	conn.add(instanceURI, factory.createURI(vocab,"class2"), factory.createLiteral(prts[29]));
			    	bol = true ;
			    	if (Integer.parseInt(prts[30])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"isExplicitClass2"), factory.createLiteral(bol));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalWordsClass2"), factory.createLiteral(Integer.parseInt(prts[32])));
			    	conn.add(instanceURI, factory.createURI(vocab,"avgClassesWords"), factory.createLiteral(Double.parseDouble((prts[33]))));
				
			    	conn.add(instanceURI, factory.createURI(vocab,"nouns"), factory.createLiteral(prts[34]));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalNounds"), factory.createLiteral(Integer.parseInt(prts[35])));
			    	
			    	conn.add(instanceURI, factory.createURI(vocab,"adjectives"), factory.createLiteral(prts[36]));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalAdjectives"), factory.createLiteral(Integer.parseInt(prts[37])));
			    
			    	conn.add(instanceURI, factory.createURI(vocab,"verbs"), factory.createLiteral(prts[38]));
			    	conn.add(instanceURI, factory.createURI(vocab,"totalVerbs"), factory.createLiteral(Integer.parseInt(prts[39])));
			    	
			    	conn.add(instanceURI, factory.createURI(vocab,"questionType"), factory.createLiteral(prts[40]));
			    	conn.add(instanceURI, factory.createURI(vocab,"answerType"), factory.createLiteral(prts[41]));
			    	
			    //	conn.add(instanceURI, factory.createURI(vocab,"isBooleanAnswer"), factory.createLiteral(prts[42]));
			    //conn.add(instanceURI, factory.createURI(vocab,"isNumberAnswer"), factory.createLiteral(prts[43]));
			    //	conn.add(instanceURI, factory.createURI(vocab,"isListAnswer"), factory.createLiteral(prts[44]));
			    	bol = true ;
			    	if (Integer.parseInt(prts[45])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"IN"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[46])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"JJ"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[47])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"JJR"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[48])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"JJS"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[49])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"NN"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[50])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"NNS"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[51])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"NNP"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[52])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"NNPS"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[53])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"PRP"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[54])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"RB"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[55])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"RBR"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[56])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"RBS"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[57])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"VB"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[58])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"VBD"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[59])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"VBG"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[60])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"VBN"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[61])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"VBP"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[62])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"VBZ"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[63])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"WDT"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[64])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"WP"), factory.createLiteral(bol));
			    	bol = true ;
			    	if (Integer.parseInt(prts[65])==0)
			    		bol = false; 
			    	conn.add(instanceURI, factory.createURI(vocab,"SYM"), factory.createLiteral(bol));
			    	conn.add(instanceURI, factory.createURI(vocab,"sparqlQuery"), factory.createLiteral(prts[72]));
			    	System.out.println(prts[72]);
			    	Query query = QueryFactory.create(prts[72]);
			    	if (query.getQueryType() == 111)
			    	conn.add(instanceURI, factory.createURI(vocab,"sparqlQueryType"), factory.createLiteral("Select"));
			    	else
			    		conn.add(instanceURI, factory.createURI(vocab,"sparqlQueryType"), factory.createLiteral("Ask"));
			    	
			    	conn.add(instanceURI, factory.createURI(vocab,"tps"), factory.createLiteral(getTpsCount(query)));
			    	System.out.println(line);
			      question++;
			    }
		}
		RepositoryResult<Statement> statements =  conn.getStatements(null, null, null, true);
		Model model = Iterations.addAll(statements, new LinkedHashModel());
		return model;
	}
	
	
	public static int getTpsCount(Query q) {
		// Remember distinct subjects in this
		final Set<TriplePath> tps = new HashSet<TriplePath>();

		// This will walk through all parts of the query
		ElementWalker.walk(q.getQueryPattern(),
		    // For each element...
		    new ElementVisitorBase() {
		        // ...when it's a block of triples...
		        public void visit(ElementPathBlock el) {
		            // ...go through all the triples...
		            Iterator<TriplePath> triples = el.patternElts();
		            while (triples.hasNext()) {
		                        	tps.add(triples.next());
		               
		            }
		        }
		    }
		);
		return tps.size();
	}

	/**
	 * Write the model into file
	 * @throws RepositoryException
	 * @throws FileNotFoundException
	 * @throws RDFHandlerException
	 */
	public static void writeModel(Model model,String outputFile) throws RepositoryException, FileNotFoundException, RDFHandlerException {
		
		OutputStream output = new FileOutputStream(new File(outputFile));
		Rio.write(model, output, RDFFormat.TURTLE);
		System.out.println("Done! Benchmark saved to "+outputFile);

	}
}
