package cz.vutbr.feec.utko.opencv.operators.RandomNoise;

import java.awt.Point;
import java.util.List;
import java.util.Vector;

import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.rapidminer.operator.Operator;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.ports.InputPort;
import com.rapidminer.operator.ports.OutputPort;
import com.rapidminer.parameter.ParameterType;
import com.rapidminer.parameter.ParameterTypeInt;
import com.rapidminer.parameter.ParameterTypeMatrix;

import cz.vutbr.feec.utko.opencv.io.OpenCVIOObject;

public class RandomNoiseOperator extends Operator {

	/**
	 * Input image
	 */
	protected InputPort inOpenCV = getInputPorts().createPort("gray image in");
	
	/**
	 * Output image with noise
	 */
	protected OutputPort outOpenCV = getOutputPorts().createPort("gray image out");
	
	private final String SEED     = "Initial seed";
	private final String POINTS   = "Points";
	private final String BURST    = "Burst Points";
	private final String VARIANCE = "Burst Variance";
	private final String PARAMETER_MATRIX = "Point Matrix";
	
	/**
	 * Create an object
	 * @param description
	 */
	public RandomNoiseOperator(OperatorDescription description) {
		super(description);
		// TODO Auto-generated constructor stub
	}

	private Vector<Point> ConvertMatrixToVector() throws OperatorException 
	{
		Vector<Point> points = new Vector<Point>();
		
		System.out.println("test");
		// fill points v	ector (rows vector)
		
		double [][] matrix = null;
		
		matrix = getParameterAsMatrix(PARAMETER_MATRIX);
		
		if(matrix == null)
			return points;
		
		for(int i=0; i<matrix.length; i++)
		{
			for(int j=0; j<matrix[0].length; j++)
			{
				System.out.println(matrix[i][j] + ", ");				
			}
			System.out.println();
		}
		
		for(int i=0; i<matrix.length; i++)
		{
			points.add(new Point((int)matrix[i][0], (int)matrix[i][1]));
		}
		
		return points;
	}
	
	/**
	 * The process of the operator
	 */
	public void doWork() throws OperatorException {
	
		OpenCVIOObject cvIO = inOpenCV.getData();
		IplImage img = cvIO.getImage();
		
		int seed = getParameterAsInt(SEED);
		int points = getParameterAsInt(POINTS);
		int burstPoints = getParameterAsInt(BURST);
		int burstVariance = getParameterAsInt(VARIANCE);
		
		PseudoRandomNoise psn = new PseudoRandomNoise(seed);
		
		IplImage output = null;
		
		// if we can used a list of points
		Vector<Point> vecPoints = ConvertMatrixToVector();
		
		try {
			if(burstPoints<1)
			{
				// generate only points
				if(vecPoints.size() > 0)
					output = psn.DrawRandomPoints(img, vecPoints);
				else
					output = psn.DrawRandomPoints(img, points);
			}
			else
			{
				// generate burst of the points
				if(vecPoints.size() > 0)
					output = psn.DrawRandomPoints(img, vecPoints, burstPoints, burstVariance);
				else
					output = psn.DrawRandomPoints(img, points, burstPoints, burstVariance);
			}
		} catch (Exception e) {
			throw new OperatorException(new String("Error int the PseudoRandomNoise implementation."));
		}
				
		outOpenCV.deliver(new OpenCVIOObject(output));
	}
	
	/**
	 * Gui properties
	 */
	public List<ParameterType> getParameterTypes() {
		List<ParameterType> types = super.getParameterTypes();
		
		types.add(new ParameterTypeInt(POINTS, "Count of the random points.", 1, Integer.MAX_VALUE, 1000));
		types.add(new ParameterTypeInt(BURST, "Count of the burst points.", 0, 1000, 0));
		types.add(new ParameterTypeInt(VARIANCE, "Variance of the burst points.", 0, 1000, 20));
		types.add(new ParameterTypeInt(SEED, "The initial seed for the random generator.", Integer.MIN_VALUE, Integer.MAX_VALUE, 0));
		types.add(new ParameterTypeMatrix(PARAMETER_MATRIX, "Row vector of the points.", "points vector", "index", "component", false));
		return types;
	}
}
