package ch.psi.plot.xyz.generator;

import ch.psi.plot.xy.generator.Noise;


/**
 * Converter to convert a simple text file to a xy series
 */
public class XYZGenerator {
	
	// X Settings
	private final double startX;
	private final double stepSizeX;
	private final int stepsX;
	private double currentStepX;
	
	// Y Settings
	private final double startY;
	private final double stepSizeY;
	private final int stepsY;
	private double currentStepY;
	
	
	/**
	 * Function to use by the generator
	 */
	private final XYZGeneratorFunction function;
	/**
	 * Noise generator
	 */
	private final Noise noiseGeneratorX;
	private final Noise noiseGeneratorY;

	
	/**
	 * Constructor
	 * @param function		Function to use for generating data
	 * @param noise			Add some noise to the generated x  value
	 */
	public XYZGenerator(XYZGeneratorFunction function, double startX, double stepSizeX, int stepsX, double startY, double stepSizeY, int stepsY, boolean noise){
		this.function = function;
		
		this.startX = startX;
		this.stepSizeX = stepSizeX;
		this.stepsX = stepsX;
		this.currentStepX = 0;
		
		this.startY = startY;
		this.stepSizeY = stepSizeY;
		this.stepsY = stepsY;
		this.currentStepY = 0;
		
		if(noise){
			this.noiseGeneratorX = new Noise(stepSizeX);
			this.noiseGeneratorY = new Noise(stepSizeY);
		}
		else{
			this.noiseGeneratorX = null;
			this.noiseGeneratorY = null;
		}
	}
	

	/**
	 * Get new data point
	 * @return	Returns null if there is no new point. Otherwise array of double (of size 3) where array[0] == x,
	 * 			array[1] == y, array[2]==z
	 */
	public double[] getNewPoint(){
		
		// Check whether X axis is at the end
		if(currentStepX>stepsX){
			currentStepX = 0;
			currentStepY++;
		}
		
		// Check whether Y axis is at the end
		if(currentStepY>stepsY){
			return(null);
		}
		
		double x = startX+(stepSizeX*currentStepX);
		if(noiseGeneratorX != null){
			x = noiseGeneratorX.generate(x);
		}
		currentStepX++;
		
		double y = startY+(stepSizeY*currentStepY);
		if(noiseGeneratorY != null){
			y = noiseGeneratorY.generate(y);
		}
		
		
		// Get y value for x
		double z = function.generate(x,y);
		
		return(new double[] {x, y, z});
	}
	
	/**
	 * Reset generator to start settings
	 */
	public void reset(){
		this.currentStepX = this.startX;
		this.currentStepY = this.startY;
	}

}
