package org.eclipse.scanning.points;

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

import org.eclipse.dawnsci.analysis.dataset.roi.LinearROI;
import org.eclipse.scanning.api.points.AbstractGenerator;
import org.eclipse.scanning.api.points.GeneratorException;
import org.eclipse.scanning.api.points.IPosition;
import org.eclipse.scanning.api.points.Point;
import org.eclipse.scanning.api.points.PointsValidationException;
import org.eclipse.scanning.api.points.models.OneDEqualSpacingModel;

public class OneDEqualSpacingGenerator extends AbstractGenerator<OneDEqualSpacingModel> {

	OneDEqualSpacingGenerator() {
		setLabel("Line Equal Spacing");
		setDescription("Creates a line scan along a line defined in two dimensions.");
		setIconPath("icons/scanner--line.png"); // This icon exists in the rendering bundle 
	}

	@Override
	protected void validateModel() {
		if (model.getPoints() < 1) throw new PointsValidationException("Must have one or more points in model!", model, "points");
	}

	@Override
	public Iterator<IPosition> iteratorFromValidModel() {
		try {
			return createPoints().iterator();
		} catch (GeneratorException e) {
			throw new IllegalArgumentException("Cannot generate an iterator!", e);
		}
	}

	@Override
	public List<IPosition> createPoints() throws GeneratorException {
		// FIXME: Make this work with just a bounding line (i.e. no ROI).

		// FIXME: This code can be called without validateModel() ever having been run.
		// Therefore, we call validateModel() manually here. What we should do is move
		// the geometry/maths to iteratorFromValidModel() (in line with the other
		// generators here) rather than overriding AbstractGenerator.createPoints().
		// Then we wouldn't need to manually call validateModel().
		//
		// However, all these generators are to be rewritten in Python (supposedly)
		// so this fix might as well wait until then.
		//
		// For the moment, just call validateModel() here...
		validateModel();
		
		if (containers==null) throw new GeneratorException("For "+getClass().getName()+" a "+LinearROI.class.getName()+" must be provided!");
		if (containers.size()!=1) throw new GeneratorException("For "+getClass().getName()+" a single "+LinearROI.class.getName()+" must be provided!");
		LinearROI roi = (LinearROI)containers.get(0).getROI();

		double length = model.getBoundingLine().getLength();
		double proportionalStep = (length / model.getPoints()) / length;
		double start = proportionalStep / 2;
		
		List<IPosition> pointsList = new ArrayList<>();
		for (int i = 0; i < model.getPoints(); i++) {
			// LinearROI has a helpful getPoint(double) method which returns coordinates of a point at a normalised
			// distance along the line
			double[] pointArray = roi.getPoint(start + i * proportionalStep);
			pointsList.add(new Point(model.getxName(), i, pointArray[0], model.getyName(), i, pointArray[1], false));
		}
		return pointsList;
	}

}

@@ -35,36 +35,8 @@
 s;%0A%0A
-import java.util.ArrayList;%0A
 impo
@@ -312,54 +312,8 @@
 on;%0A
-import org.eclipse.scanning.api.points.Point;%0A
 impo
@@ -442,16 +442,71 @@
 ngModel;
+%0Aimport org.eclipse.scanning.points.ScanPointGenerator;
 %0A%0Apublic
@@ -2309,16 +2309,18 @@
 ROI();%0A%0A
+//
 %09%09double
@@ -2366,16 +2366,18 @@
 ngth();%0A
+//
 %09%09double
@@ -2435,16 +2435,18 @@
 length;%0A
+//
 %09%09double
@@ -2479,16 +2479,18 @@
 / 2;%0A%09%09%0A
+//
 %09%09List%3CI
@@ -2531,16 +2531,18 @@
 st%3C%3E();%0A
+//
 %09%09for (i
@@ -2581,16 +2581,18 @@
  i++) %7B%0A
+//
 %09%09%09// Li
@@ -2690,16 +2690,18 @@
 malised%0A
+//
 %09%09%09// di
@@ -2722,16 +2722,18 @@
 he line%0A
+//
 %09%09%09doubl
@@ -2793,16 +2793,18 @@
 lStep);%0A
+//
 %09%09%09point
@@ -2904,20 +2904,444 @@
 alse));%0A
+//
 %09%09%7D%0A
+//%09%09double step = length / model.getPoints();%0A%09%09%0A%09%09ScanPointGenerator spg = new ScanPointGenerator();%0A%09%09String%5B%5D names = %7BString.format(%22'%25s'%22, model.getxName()), String.format(%22'%25s'%22, model.getyName())%7D;%0A%09%09double%5B%5D start = roi.getPoint();%0A//%09%09TODO: start%5B0%5D += step/2 etc%0A%09%09double%5B%5D stop = roi.getEndPoint();%0A%09%09%0A%09%09List%3CIPosition%3E pointsList = spg.create2DLinePoints(names, %22'mm'%22, start, stop, model.getPoints(), false);%0A
 %09%09return

Refactor OneDEqualSpacingGenerator to use LineGenerator