package com.artemis.utils;

import java.util.NoSuchElementException;

/**
 * Base iterator for {@link IntBag}
 * 
 * example use 
 * 
 * IntBag ids;
 * ....
 * final IntBagIterator it = new IntBagIterator(ids);
 * while (it.hasNext())
 *    doSomething(it.next());
 *
 * or
 * 
 * for (final IntBagIterator it = new IntBagIterator(ids); it.hasNext();)
 *    doSomething(it.next());
 *  
 */
public class IntBagIterator {

    protected static enum State {
        INIT,
        NEXT_CALLED,
        REMOVE_CALLED,
    }

	protected final IntBag intBag;
	protected int index;
	protected int indexEnd;
	protected State state;

	/**
	 * Create iterator for IntBag
	 * @return true if the iteration has more elements
	 */
	public IntBagIterator(final IntBag intBag) {
		this.intBag = intBag;
		index = -1;
		indexEnd = intBag != null ? intBag.size() : 0;
		assert indexEnd >= 0;
		state = State.INIT;
	}
	
	/**
	 * Create iterator for IntBag
	 * @return true if the iteration has more elements
	 */
	public IntBagIterator(final IntBag intBag, final int indexBegin) {
		this.intBag = intBag;
		assert indexBegin >= 0;
		this.index = indexBegin - 1;
		indexEnd = intBag != null ? intBag.size() : 0;
		assert indexEnd >= 0;
		state = State.INIT;
	}
	
	/**
	 * Create iterator for IntBag
	 * @return true if the iteration has more elements
	 */
	public IntBagIterator(final IntBag intBag, final int indexBegin, final int size) {
		this.intBag = intBag;
		assert indexBegin >= 0;
		this.index = indexBegin - 1;
		indexEnd = intBag != null ? (size < intBag.size() ? size : intBag.size()) : 0;
		indexEnd += indexBegin;
		assert indexEnd >= 0;
		state = State.INIT;
	}
	
	/**
	 * return current index
	 * This method can be called only per call to next().
	 * This method can not be called after call remove().
	 * 
	 * @throws IllegalStateException - if the next() method has not yet been called
	 */
	public int getCurrentIndex() {
		if (state == State.NEXT_CALLED && index < indexEnd && indexEnd <= intBag.size()) {
			return index;
		}
		throw new IllegalStateException(getErrorMessage(index));
	}

	/**
	 * Returns true if the iteration has more elements. (In other words, returns true if next() would return an element rather than throwing an exception.)
	 * @return true if the iteration has more elements
	 */
	public boolean hasNext() {
		return index + 1 < indexEnd && indexEnd <= intBag.size();
	}

	/**
	 * Returns the next element in the iteration.
	 * @return the next element in the iteration
	 * 
	 * @throws NoSuchElementException - if the iteration has no more elements
	 */
	public int next() {
		final int newIndex = index + 1;

		if (newIndex < indexEnd && indexEnd <= intBag.size()) {
			index = newIndex;
			state = State.NEXT_CALLED;
			return intBag.getData()[index];
		}
		
		throw new NoSuchElementException(getErrorMessage(newIndex));
	}
	
	/**
	 * Removes from the underlying collection the last element returned by this iterator (optional operation).
	 * This method can be called only once per call to next().
	 * The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.
	 * 
	 * @throws IllegalStateException - if the next() method has not yet been called, or the remove() method has already been called after the last call to the next() method
	 */
	public void remove() {
		if (state == State.NEXT_CALLED && index < indexEnd && indexEnd <= intBag.size()) {
			intBag.remove(index);
			index--;
			indexEnd--;
			assert index < indexEnd;
		}
		throw new NoSuchElementException(getErrorMessage(index));
	}
	
	/**
	 * generate error message
	 */
	private String getErrorMessage(final int indexVal) {
		final String message = "Tried accessing element: " + indexVal + "/" + indexEnd + "/" + intBag.size() + "/" + state.name();
		return message;
	}
	
}

@@ -1514,53 +1514,46 @@
 = in
-tBag != null ? (size %3C intBag.size() ? size :
+dexBegin + size;%0A%09%09final int allSize =
  int
@@ -1562,21 +1562,16 @@
 g.size()
-) : 0
 ;%0A%09%09inde
@@ -1579,21 +1579,72 @@
 End 
-+= indexBegin
+= intBag != null ? (indexEnd %3C allSize ? indexEnd : allSize) : 0
 ;%0A%09%09

fix some error in IntBagIterator