package eu.dnetlib.enabling.resultset.push;

import java.io.Serializable;
import java.util.Iterator;

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

/**
 * Describes a push resultset.
 *
 * <p>
 * A push resultset stores it's data in several ranges
 * </p>
 *
 * @author marko
 *
 */
public class ResultSetDescriptor implements Serializable {

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

	/**
	 * This class describes a range.
	 *
	 * @author marko
	 *
	 */
	public class Range {
		private int range;
		private int begin;
		private int end;

		public Range(final int range, final int begin, final int end) {
			super();
			this.range = range;
			this.begin = begin;
			this.end = end;
		}

		@Override
		public String toString() {
			return "Range(" + range + ", " + begin + ", " + end + ")";
		}

		public int getRange() {
			return range;
		}

		public void setRange(final int range) {
			this.range = range;
		}

		public int getBegin() {
			return begin;
		}

		public void setBegin(final int begin) {
			this.begin = begin;
		}

		public int getEnd() {
			return end;
		}

		public void setEnd(final int end) {
			this.end = end;
		}
	}

	/**
	 *
	 */
	private static final long serialVersionUID = 7699992350256317181L;

	private int rangeLength = 100;

	private int ranges = 0;

	public int getLastRange() {
		return ranges - 1;
	}

	/**
	 * @param fromPosition
	 *            1 based count
	 * @param toPosition
	 *            1 based count
	 * @return
	 */
	public Iterable<Range> getRangesContaining(final int fromPosition, final int toPosition) {

		final int fromRange = (fromPosition - 1) / rangeLength;
		int ttoRange = (int) Math.ceil((toPosition * 1.0) / rangeLength);

		if (ttoRange > ranges)
			ttoRange = ranges;

		final int toRange = ttoRange;

		log.debug("FROM range: " + fromRange);
		log.debug("TTO range: " + ttoRange);
		log.debug("TO range: " + toRange);

		return new Iterable<Range>() {

			@Override
			public Iterator<Range> iterator() {
				return new Iterator<Range>() {

					int current = fromRange;

					@Override
					public boolean hasNext() {
						return current < toRange;
					}

					@Override
					public Range next() {
						int begin = 0;
						int end = rangeLength;
						if (current == fromRange)
							begin = (fromPosition - 1) % rangeLength;
						if ((current + 1) == toRange)
							end = (toPosition - 1) % rangeLength + 1;
						return new Range(current++, begin, end);
					}

					@Override
					public void remove() {
						throw new IllegalStateException("text");
					}
				};
			}
		};
	}

	public int getRangeLength() {
		return rangeLength;
	}

	public void setRangeLength(final int rangeLength) {
		this.rangeLength = rangeLength;
	}

	public int getRanges() {
		return ranges;
	}

	public void setRanges(final int ranges) {
		this.ranges = ranges;
	}
}
