package eu.dnetlib.enabling.resultset.client;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import eu.dnetlib.enabling.resultset.client.utils.ResultSetRuntimeException;
import eu.dnetlib.enabling.resultset.client.utils.ResultSetTimeoutException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;

/**
 * 
 * @author claudio
 *
 */
public class ResultSetClientIterator implements Iterator<String> {

	/**
	 * logger
	 */
	private static final Log log = LogFactory.getLog(ResultSetClientIterator.class);
	
	/**
	 * the page source 
	 */
	private ResultSetPageProvider pageProvider;
	
	/**
	 * buffer used to provide a single element for the next() method
	 */
	private Queue<String> buffer;
	

	public ResultSetClientIterator(ResultSetService resultSet, String rsId) 
		throws ResultSetRuntimeException {
		
		pageProvider = new ResultSetPageProvider(resultSet, rsId);
		buffer = new LinkedList<String>();
	}
	
	public ResultSetClientIterator(ResultSetService resultSet, String rsId, int pageSize) {
		this(resultSet, rsId);
		pageProvider.setPageSize(pageSize);
	}
	
	public ResultSetClientIterator(ResultSetService resultSet, String rsId, int pageSize, long timeout) {
		this(resultSet, rsId, pageSize);
		pageProvider.setMaxWaitTime(timeout);
	}
	
	/**
	 * Tries to refill the buffer with a nextPage()
	 * @return true if the buffer was filled successfully, false otherwise
	 * @throws ResultSetTimeoutException in case of timeout
	 * @throws ResultSetException 
	 * @throws ResultSetException 
	 */
	private boolean refillBuffer() throws ResultSetTimeoutException, ResultSetRuntimeException {
		List<String> page = pageProvider.nextPage();
		if (page != null && !page.isEmpty()) {
			buffer.addAll(page);
			return true;
		}
		return false;
	}
	
	@Override
	public boolean hasNext() {
		if (!buffer.isEmpty())
			return true;
		return refillBuffer();
	}

	@Override
	public String next() {
		if (!hasNext()) {
			log.info("NoSuchElementException");
			throw new NoSuchElementException();
		}
		return buffer.poll();
	}

	@Override
	public void remove() {
		throw new UnsupportedOperationException();
	}

}
