package eu.dnetlib.data.utility.objectpackaging;

import java.io.StringReader;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

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.io.SAXReader;

import eu.dnetlib.data.utility.objectpackaging.rmi.ObjectPackagingException;

class ObjectQueue {
	/**
	 * 
	 */
	private static final long serialVersionUID = -8679627487574601486L;

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

	private int totalItems = 0;
	private int givenItems = 0;

	protected Queue<String> theQueue;

	private String xpath_ID;

	private ObjectProvider provider;

	private ObjectProviderFactory objectProviderFactory; 

	protected ObjectQueue(W3CEndpointReference epr, String xpath_ID, ObjectProviderFactory objectProviderFactory) throws ObjectPackagingException {
		this.provider = objectProviderFactory.createObjectProvider(epr);
		this.xpath_ID = xpath_ID;
		this.theQueue = new PriorityQueue<String>();
		this.objectProviderFactory = objectProviderFactory;
		callDataProvider();
	}

	private void callDataProvider() throws ObjectPackagingException {
		if (provider == null) throw new ObjectPackagingException("Problem with DataProvider: provider is null");
		try {
			totalItems = provider.getSize();
		} catch (Exception e) {
			throw new ObjectPackagingException("Problem with DataProvider: " + e.getMessage()); 
		}

	}

	public boolean isEmpty() {
		if (givenItems == totalItems) return true;
		return false;
	}

	public String fetchNextElement() throws ObjectPackagingException {
		if (theQueue.isEmpty() && (givenItems < totalItems)) {
			retrieveMoreElements();
		}
		String response = theQueue.poll();
		if (response != null) givenItems += 1;
		return response;
	}

	public String watchNextElementId() throws ObjectPackagingException {
		if (theQueue.isEmpty() && (givenItems < totalItems)) {
			retrieveMoreElements();
		}
		String elem = theQueue.peek();
		if (elem == null) return null;

		return calculateID(elem);
	}

	private String calculateID(String s) throws ObjectPackagingException {
		try {
			SAXReader reader = new SAXReader();
			Document doc = reader.read(new StringReader(s));

			String res = doc.valueOf(xpath_ID);
			if ((res == null)||(res.length() == 0)) {
				throw new ObjectPackagingException("xpath " + xpath_ID + " has returned an empty identifier");
			}
			return res;
		} catch (DocumentException e) {
			throw new ObjectPackagingException(e);
		}
	}

	private void retrieveMoreElements() throws ObjectPackagingException {
		int from = givenItems + 1;
		int to   = from       + ObjectPackagesCollection.DEFAULTPAGESIZE - 1;
		if (to > totalItems) to = totalItems;

		List<String> res = provider.getElements(from, to);
		theQueue.addAll(res);
	}

	protected int getGivenItems() {
		return givenItems;
	}

	public int getTotalItems() {
		return totalItems;
	}

	public List<String> obtainOldItems(int from, int to) throws ObjectPackagingException {
		return provider.getElements(from, to);
	}

	public ObjectProviderFactory getObjectProviderFactory() {
		return objectProviderFactory;
	}

	public void setObjectProviderFactory(ObjectProviderFactory objectProviderFactory) {
		this.objectProviderFactory = objectProviderFactory;
	}

}
