package coll;
/* Immutable Collection
 * by Martin Robinson
 * \__________________/
 *       /
 * \ ('<
 * (<=)
 * */
/* Range list generator
 * this is the most usefull
 * generator of all, many
 * time we needed a list
 * filled with consecutive
 * number for iteration or
 * simple calculus, then it
 * is. but as you may found
 * it does not store the
 * array but only what he
 * need to calculate it.
 * With this one, you can
 * blast off:
 * for (Integer i : Range.fromZeroTo(57))
 *   ....
 * instead off:
 * for (int i=0;i<57;i++)
 *   ....
 * \___________________/
 *      /
 * \ ('<
 * (<=)
 * */
import calc.Num;

/**
 * @author martin
 *range generator
 * @param <E>
 */
public final class Range extends Coll<Number>{
	private final Number _from,
	                _to,
	                _step;
	/**
	 * private factory
	 * @param from as number
	 * @param to as number
	 * @param step as number
	 */
	private Range(final Number from, final Number to, final Number step){
		_from = from;
		_to = to;
		_step = step;
	}
	/**
	 * static factory
	 * @param to as number
	 * @return new range generated
	 */
	public static Lst<Number> fromZeroTo(final Number to){
		if(to == null)
			throw new NullPointerException();
		if(Num.lower(to,0))
			return new Range(to,0,-1);
		return new Range(0,to,1);
	}
	/**
	 * static factory
	 * @param from as number
	 * @param to as number
	 * @return new range generated
	 */
	public static Lst<Number> fromRange(final Number from, final Number to){
		if (from ==null || to == null)
			throw new NullPointerException();
		if (Num.greater(from,to))
			return new Range(to, from, -1);
		return new Range(from, to, 1);
	}
	/**
	 * static factory
	 * @param from as number
	 * @param to as number
	 * @param step as number
	 * @return new range generated
	 */
	public static Lst<Number> fromStep(final Number from, final Number to, final Number step){
		if (from ==null || to == null || step == null)
			throw new NullPointerException();
		if ((Num.greater(from, to) && Num.greater(step, 0)) || (Num.lower(from, to) && Num.lower(step, 0)))
			return new Range(to,from,step);
		return new Range(from, to, step);
	}

	/* (non-Javadoc)
	 * @see coll.Lst#get(int)
	 */
	public Number get(int i) {
		if (i<size())
			return Num.add(_from, Num.mul(_step, i));
		throw new ArrayIndexOutOfBoundsException();
	}
	/* (non-Javadoc)
	 * @see coll.Lst#size()
	 */
	public int size() {
		return Num.div(Num.sub(_to,_from),_step).intValue();
	}
	/* (non-Javadoc)
	 * @see coll.Lst#undo()
	 */
	public Lst<Number> undo() {
		return null;
	}
}
