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.provision.index.rmi.IndexService;
import eu.dnetlib.data.provision.index.rmi.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<IndexService> 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 List<String> browseFields,
			final String metadataFormat,
			final String layout,
			final String interpretation) throws IndexServiceException {
		List<BrowseCategory> list = new ArrayList<BrowseCategory>();

		String browseQuery = calculateBrowseQuery(cqlQuery, browseFields);

		W3CEndpointReference epr = indexLocator.getService().browse(browseQuery, metadataFormat, layout, interpretation);

		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(final String cqlQuery, final 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<IndexService> getIndexLocator() {
		return indexLocator;
	}

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

	public int getMaxElementsForCategory() {
		return maxElementsForCategory;
	}

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

}
