package eu.dnetlib.functionality.lightui.browse;

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

import javax.annotation.Resource;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Required;

import eu.dnetlib.data.index.IIndexService;
import eu.dnetlib.data.index.IndexServiceException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
import eu.dnetlib.enabling.tools.ServiceLocator;
import eu.dnetlib.functionality.lightui.utils.ResultSet;
import eu.dnetlib.functionality.lightui.utils.ResultSetFactory;

public class BrowseStatsEngine {
	
	@Resource(name="lightuiResultSetFactory")
	protected ResultSetFactory resultSetFactory;
	
	protected ServiceLocator<IIndexService> indexLocator;

	private int maxElementsForCategory;
	
	private static final Log log = LogFactory.getLog(BrowseStatsEngine.class); // NOPMD by marko on 11/24/08 5:02 PM

	
	public List<BrowseCategory> getBrowseStats(final String cqlQuery, final String metadataFormat, List<String> browseFields) throws IndexServiceException {
		List<BrowseCategory> list = new ArrayList<BrowseCategory>();
		
		String browseQuery = calculateBrowseQuery(cqlQuery, browseFields);

		W3CEndpointReference epr = indexLocator.getService().getBrowsingStatistics(browseQuery, "all", metadataFormat, "index");

		ResultSet rs = resultSetFactory.newInstance(epr);

		SAXReader reader = new SAXReader();

		try {
			int tot = rs.getNumberOfElements();
			
			if (tot > maxElementsForCategory) tot = maxElementsForCategory;
			
			if (tot > 0) {
				for (String s : rs.getResult(1, tot)) {
					Document doc = reader.read(new StringReader(s));
					
					for (Object o : doc.selectNodes("//groupresult")) {
						Node node = (Node) o;
						String catName = node.valueOf("@field");
						String valName = node.valueOf("./value");
						int valSize = Integer.parseInt(node.valueOf("./count"));
	
						boolean notFound = true;
						for (int i=0; i<list.size() && notFound; i++) {
							BrowseCategory elem = list.get(i);
							if (elem.getCategoryName().equals(catName)) {
								elem.insertElement(valName, valSize);
								notFound = false;
							}
						}
						if (notFound) {
							BrowseCategory elem = new BrowseCategory(catName, cqlQuery);
							elem.insertElement(valName, valSize);
							list.add(elem);
						}
					}

				}
			}
		} catch (ResultSetException e) {
			log.error("Error accessing resultset", e);
		} catch (DocumentException e) {
			log.error("Error parsing xml", e);
		}
		return list;
	}


	private String calculateBrowseQuery(String cqlQuery, List<String> browseFields) {
		String browseQuery = null;
		
		for (String s : browseFields) {
			if (browseQuery == null) {
				browseQuery = "query=" + cqlQuery + "&groupby=" + s;
			} else {
				browseQuery += "," + s;
			}
		}
		
		return browseQuery;
	}
	
	
	public ServiceLocator<IIndexService> getIndexLocator() {
		return indexLocator;
	}

	@Required
	public void setIndexLocator(ServiceLocator<IIndexService> indexLocator) {
		this.indexLocator = indexLocator;
	}


	public int getMaxElementsForCategory() {
		return maxElementsForCategory;
	}

	@Required
	public void setMaxElementsForCategory(int maxElementsForCategory) {
		this.maxElementsForCategory = maxElementsForCategory;
	}
	
}
