package eu.dnetlib.enabling.resultset;

import java.util.ArrayList;
import java.util.List;

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

/**
 * an open ResultSet that can be iterated to get it's data results.
 * 
 * @author claudio
 * 
 */
public class IterableResultSet implements ResultSetListener, ResultSetAware {

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(IterableResultSet.class);

	/**
	 * the container for the data results.
	 */
	private ResultSet resultSet;

	/**
	 * the list that provides data for this resultSet.
	 */
	private FetchList<String> fetchList;

	private int optionalNumberOfElements;

	/**
	 * 
	 * @param iter
	 * @param fetchSize
	 */
	protected IterableResultSet(Iterable<String> iter, int fetchSize) {
		fetchList = new FetchList<String>(iter.iterator(), fetchSize);
		if (iter instanceof SizedIterable<?>) {
			optionalNumberOfElements = ((SizedIterable<?>) iter).getNumberOfElements();
		} else {
			optionalNumberOfElements = -1;
		}
	}

	/**
	 * @param fromPosition
	 * @param toPosition
	 * @return <T> List
	 */
	@Override
	public List<String> getResult(int fromPosition, int toPosition) {

		log.debug(" - getting result from " + fromPosition + " to " + toPosition + ", consumedElements: " + fetchList.getConsumedElements());

		if (fromPosition != fetchList.getConsumedElements() + 1)
			throw new RuntimeException("Unexpected value for 'fromPosition' parameter");
		if (toPosition < fromPosition)
			throw new RuntimeException("'fromPosition' must be lower or equal than 'toPosition'");

		List<String> result = new ArrayList<String>();

		for (int i = fromPosition; i <= toPosition; i++) {
			if (fetchList.size() > 0)
				result.add(fetchList.poll());
			else
				break;
		}

		ensureClosed();

		return result;
	}

	private void ensureClosed() {
		if (fetchList.size() == 0 && resultSet.isOpen()) {
			log.info(">>>>>>>>>>> closing resultset <<<<<<<<<<<<<");
			close();
		}
	}

	public String getRSStatus() {
		if (resultSet.isOpen())
			return "open";
		return "closed";
	}

	@Override
	public int getSize() {
		ensureClosed();

		if (optionalNumberOfElements == -1)
			return fetchList.getTotalElements();
		else
			return optionalNumberOfElements;
	}

	/**
	 * closes the resultset.
	 */
	protected void close() {
		resultSet.close();
	}

	@Override
	public void setResultSet(ResultSet resultSet) {
		this.resultSet = resultSet;
	}

	public ResultSet getResultSet() {
		return resultSet;
	}

}
