package com.k_int.npdb.service;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xpath.XPathAPI;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.k_int.aggregator.core.DepositResult;
import com.k_int.aggregator.plugin.XMLDocumentHandlerPlugin;
import com.k_int.aggregator.plugin.XMLProcessingResult;
import com.k_int.aggregator.util.SOLRHelper;
import com.k_int.aggregator.util.SOLRHelper.NVPair;
import com.k_int.npdb.datamodel.Work;


@Service("XMLHandler-NPDB")
public class NPDBHandler implements XMLDocumentHandlerPlugin, ApplicationContextAware {

	private ApplicationContext ctx;
	private SessionFactory sf;
    private static Log log = LogFactory.getLog(NPDBHandler.class);

	
	private static final String works_xpath = "/npdb:data/npdb:works/npdb:work";
	private static final String productions_xpath = "/npdb:data/npdb:productions/npdb:production";
	private static final String performance_xpath = "/npdb:data/npdb:performances/npdb:performance";
	private static final String agents_xpath = "/npdb:data/npdb:agents/npdb:agent";
	private static final String venues_xpath = "/npdb:data/npdb:venues/npdb:venue";
	  
	   
	public static String XMLNS_XSI = "http://www.w3.org/2001/XMLSchema-instance";
	public static String XMLNS_NPDB = "http://www.k-int.com/npdb";
	 
	public String[] getSupportedSchemas() {
		return new String[]{XMLNS_NPDB};
	}
	
	
	public NPDBHandler(){
		log.debug("NPDBHandler");
	}
	
	
	public void setApplicationContext(ApplicationContext ctx){
		this.ctx = ctx;
	}

	public XMLProcessingResult process(DepositResult depositResult,
			byte[] content, Document d, String depositor_id, String owner_id,
			String root_namespace, Boolean authoritative) {
		return process (depositResult, content, d, depositor_id, owner_id, root_namespace, authoritative, 0);
	}
	
	
	public XMLProcessingResult process(DepositResult depositResult,
			byte[] content, Document d, String depositor_id, String owner_id,
			String root_namespace, Boolean authoritative, long options) {
		log.debug("Processing NPDB");
		XMLProcessingResult result = new XMLProcessingResult();
		Transaction tx = null;
		sf = (SessionFactory)ctx.getBean("AggregatorSessionFactory");
		Session sess = SessionFactoryUtils.getSession(sf,true);
		try {
			tx = sess.beginTransaction();
			Element namespaceNode = d.createElement("NSNode");
		    namespaceNode.setAttribute("xmlns:xsi", XMLNS_XSI);
		    namespaceNode.setAttribute("xmlns:npdb", XMLNS_NPDB);
		    NodeList works = XPathAPI.selectNodeList(d, works_xpath, namespaceNode);
			SOLRHelper solrHelper = (SOLRHelper)ctx.getBean("SolrHelper");
			for (int i = 0; i < works.getLength(); i++)
		    {
				List<NVPair> index_properties = new ArrayList<NVPair>();
				Node n = works.item(i);
		    	String id = getString(n, "npdb:id", namespaceNode);
		    	String name = getString(n, "npdb:name", namespaceNode);
		    	String genre = getString(n, "npdb:genre", namespaceNode);
		    	NodeList contributors = XPathAPI.selectNodeList (n, "npdb:contributor/npdb:name", namespaceNode);
		    	index_properties.add(new SOLRHelper.NVPair("identifier", "work_" + id));
			    index_properties.add(new SOLRHelper.NVPair("name", name));
			    index_properties.add(new SOLRHelper.NVPair("type", "work"));
			    if (genre!=null)
			    	index_properties.add(new SOLRHelper.NVPair("genre", genre));
			    Work work =  new Work();
			    work.setName(name);
			    work.setExternalId(id);
			    work.setGenre(genre);
			    sess.save(work);
			    sess.flush();
			    tx.commit();
			    for (int j=0; j<contributors.getLength(); j++)
			    {
			    	Node contributor = contributors.item(j);
			    	String value = contributor.getTextContent();
			    	if (value!=null)
			    		index_properties.add(new SOLRHelper.NVPair("person", value));
			    }
			    solrHelper.postIndexEntries(index_properties, false);
		    }
			
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	

	private String getString(Node metadata_record, String xpath,
			Node namespace_node)
			throws javax.xml.transform.TransformerException {
		Node value = XPathAPI.selectSingleNode(metadata_record, xpath,
				namespace_node);
		if (value != null) {
			return extractText(value);
		}
		return null;
	}
	
	private  String extractText(Node n)
	  {
	    try
	    {
	      Node node = XPathAPI.selectSingleNode(n, "./text()");
	      if (node != null)
	      {
	        node.normalize();
	         return node.getNodeValue().trim();
	      }
	    } catch (javax.xml.transform.TransformerException te)
	    {
	      te.printStackTrace();
	    }
	    return null;
	  }

}