package eu.dnetlib.data.utility.objectpackaging;

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import javax.xml.ws.wsaddressing.W3CEndpointReference;

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

public abstract class AbstractQueue {

	private int totalItems = 0;

	private int givenItems = 0;

	private Queue<String> theQueue;

	private ObjectProvider provider;

	private ObjectProviderFactory objectProviderFactory;

	protected AbstractQueue(W3CEndpointReference epr, ObjectProviderFactory objectProviderFactory) throws ObjectPackagingException {
		this.provider = objectProviderFactory.createObjectProvider(epr);
		this.theQueue = new LinkedList<String>(); // LinkedLists can be used as queue 
		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(), e);
		}

	}

	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 watchNextElement() throws ObjectPackagingException {
		if (theQueue.isEmpty() && (givenItems < totalItems)) {
			retrieveMoreElements();
		}
		String elem = theQueue.peek();
		if (elem == null) {
			return null;
		}

		return elem;
	}

	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;
	}

}
