package fr.iri.thd.sonyengine.web;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import thd.Neighbor;

import com.sleepycat.je.Transaction;
import com.sleepycat.persist.EntityCursor;

import fr.iri.thd.sonyengine.core.DataAccessor;
import fr.iri.thd.sonyengine.core.DbEnv;
import fr.iri.thd.sonyengine.core.EngineAccessor;

@Path ("engine")
public class EngineResource {

	@POST
	@Path("train")
    public String train() {    	

		EngineAccessor.getInstance().train();    	
    	return "ok";
    }
    
	@POST
	@Path("train/{id}")
    public String train(@PathParam("id") String tagName) {    	

	    EngineAccessor.getInstance().train(tagName);
    	return tagName + " : ok";
    }
	
	@GET
	@Path("find/{segment}/{tag}/{percent}/{more}")
	@Produces(MediaType.APPLICATION_XML)
	public String find(
			@PathParam("segment") String segment, 
			@PathParam("tag") String tag,
			@PathParam("percent") String percent,
			@PathParam("more") String more) {
		
		float percentf = Float.parseFloat(percent);
		boolean moreb = Boolean.parseBoolean(more);
		Neighbor n =  EngineAccessor.getInstance().findMore(segment, tag, percentf, moreb);
				
		Document doc = null;
		try {
			doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		
		Element root = doc.createElement("sonyengine");
		doc.appendChild(root);
		
		if(n!= null)
		{
			Element neighborElement = doc.createElement("neighbor");
			neighborElement.setAttribute("segment", n.getMovieRef());
			neighborElement.setAttribute("distance", Double.toString(n.getDistance()));
			root.appendChild(neighborElement);
		}
		
		TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = null;
		try {
			trans = transfac.newTransformer();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		}
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");

        //create string from xml tree
        StringWriter sw = new StringWriter();
        StreamResult result = new StreamResult(sw);
        DOMSource source = new DOMSource(doc);
        try {
			trans.transform(source, result);
		} catch (TransformerException e) {
			e.printStackTrace();
		}
        return sw.toString();
		
	}
	
	@POST
	@Path("reset")
	@Produces(MediaType.TEXT_PLAIN)
	public String ResetDatabase(@Context ServletContext context) {
		
    	DbEnv dbenv = (DbEnv)context.getAttribute(ServletContainer.DB_ENV_ATTRIBUTE);
		DataAccessor da = new DataAccessor(dbenv.getEntityStore());
		
		EntityCursor<String> keyCursor = da.tagById.keys();
		List<String> keysTag = new ArrayList<String>();
		for (String key : keyCursor) {
			keysTag.add(key);	
		}
		keyCursor.close();
				
		List<String> keysMovie = new ArrayList<String>();
		
		keyCursor = da.movieFragmentById.keys();
		
		for (String key : keyCursor) {
			keysMovie.add(key);
		}
		
		keyCursor.close();
		
		Transaction trans = dbenv.getEnv().beginTransaction(null,null);
		
		for(String key : keysTag) {
			da.tagById.delete(trans,key);
		}

		//trans.commitSync();
		//trans = dbenv.getEnv().beginTransaction(null,null);
		
		for(String key : keysMovie) {
			da.movieFragmentById.delete(trans,key);
		}
		trans.commitSync();
		
		dbenv.sync();
		
		EngineAccessor.getInstance().clearAll();
		EngineAccessor.getInstance().train();
		
		return "ok";
	}

}


