package org.eclipse.scanning.points;

import java.util.Iterator;

import org.eclipse.scanning.api.points.Point;
import org.eclipse.scanning.api.points.models.GridModel;

class GridIterator implements Iterator<Point> {

	private final GridModel model;
	private final GridGenerator gen;
	private final double minX;
	private final double minY;
	private final double xStep;
	private final double yStep;

	private int i,j;

	public GridIterator(GridGenerator gen) {
		this.model = gen.getModel();	
		this.gen   = gen;
		this.xStep = model.getBoundingBox().getWidth() / model.getColumns();
		this.yStep = model.getBoundingBox().getHeight() / model.getRows();
		this.minX = model.getBoundingBox().getxStart() + xStep / 2;
		this.minY = model.getBoundingBox().getyStart() + yStep / 2;
		i = 0;
		j = -1;
	}

	private boolean forewards=true;

	@Override
	public boolean hasNext() {
		
		int[] next = increment(model, i, j, forewards); 
		int i = next[0];
		int j = next[1];
			
		if (i>(model.getRows()-1) || i<0)    {
			return false;  // Normal termination
		}
		if (j>(model.getColumns()-1) || j<0) return false;
		
		double x = minX + j * xStep;
		double y = minY + i * yStep;
		if (!gen.containsPoint(x, y)) {
			this.i = i;
			this.j = j;
			this.forewards = next[2]==1;
			return hasNext();
		}

		return true;
	}


	private static final int[] increment(GridModel model, int i, int j, boolean forewards) {
		
		if (model.isSnake()) {
			if (forewards) {
				j = j+1;
				if (j>(model.getColumns()-1)) {
					i++;
					forewards = !forewards;
				}
			} else {
				j = j-1;
				if (j<0) {
					j=0;
					i++;
					forewards = !forewards;
				}
			}

		} else {
			j++;
			if (j>(model.getColumns()-1)) {
				j=0;
				i++;
			}
		}
		return new int[]{i,j, forewards?1:0}; // Bit slow because makes array object to return int values
	}

	
	@Override
	public Point next() {
		
		int[] next = increment(model, i, j, forewards);
		this.i = next[0];
		this.j = next[1];
		this.forewards = next[2]==1;
		
		if (i>(model.getRows()-1) || i<0)    return null;  // Normal termination
		if (j>(model.getColumns()-1) || j<0) throw new NullPointerException("Unexpected index. The j index was "+j);

		double x = minX + j * xStep;
		double y = minY + i * yStep;
		if (gen.containsPoint(x, y)) {
			return new Point(model.getxName(), j, x, model.getyName(), i, y);
		} else {
			return next();
		}
	}

	public void remove() {
		throw new UnsupportedOperationException("remove");
	}

}

@@ -410,16 +410,48 @@
 int i,j;
+%0A%09private boolean forwards=true;
 %0A%0A%09publi
@@ -829,42 +829,8 @@
 %09%7D%0A%0A
-%09private boolean forewards=true;%0A%0A
 %09@Ov
@@ -904,25 +904,24 @@
 l, i, j, for
-e
 wards); %0A%09%09i
@@ -1229,33 +1229,32 @@
 = j;%0A%09%09%09this.for
-e
 wards = next%5B2%5D=
@@ -1379,25 +1379,24 @@
  boolean for
-e
 wards) %7B%0A%09%09%0A
@@ -1430,17 +1430,16 @@
 %09if (for
-e
 wards) %7B
@@ -1498,33 +1498,32 @@
 %09%09%09i++;%0A%09%09%09%09%09for
-e
 wards = !forewar
@@ -1510,33 +1510,32 @@
 %09forwards = !for
-e
 wards;%0A%09%09%09%09%7D%0A%09%09%09
@@ -1599,17 +1599,16 @@
 %09%09%09%09%09for
-e
 wards = 
@@ -1611,17 +1611,16 @@
 s = !for
-e
 wards;%0A%09
@@ -1734,25 +1734,24 @@
 t%5B%5D%7Bi,j, for
-e
 wards?1:0%7D; 
@@ -1894,17 +1894,16 @@
 , j, for
-e
 wards);%0A
@@ -1952,17 +1952,16 @@
 this.for
-e
 wards = 

Correct misspelling