package imagej.core.plugins;

import imagej.model.Dataset;
import imagej.plugin.Parameter;
import imagej.plugin.Plugin;
import mpicbg.imglib.algorithm.OutputAlgorithm;
import mpicbg.imglib.container.planar.PlanarContainerFactory;
import mpicbg.imglib.cursor.Cursor;
import mpicbg.imglib.image.Image;
import mpicbg.imglib.image.ImageFactory;
import mpicbg.imglib.type.numeric.RealType;
import mpicbg.imglib.type.numeric.real.FloatType;

/**
 * TODO
 *
 * @author Barry DeZonia
 */
@Plugin(
	menuPath = "Process>NaN Background"
)
public class SetBackgroundToNaN<T extends RealType<T>> extends ImglibOutputAlgorithmPlugin<T>
{
	// ********** instance variables ****************************************************************
	
	@Parameter
	private Dataset in;

	@Parameter
	private double loThreshold;
	
	@Parameter
	private double hiThreshold;

	// ********** public interface ****************************************************************
	
	/** basic constructor */
	public SetBackgroundToNaN()
	{
	}
	
	/** runs this plugin */
	@Override
	public void run()
	{
		if (in == null)  // TODO - temporary code to test these until IJ2 plugins can correctly fill a Dataset @Parameter
		{
			Image<FloatType> junkImage = createImage(new FloatType(), new int[]{200,200});
			Cursor<FloatType> cursor = junkImage.createCursor();
			int index = 0;
			for (FloatType pixRef : cursor)
				pixRef.set(index++);
			cursor.close();
			in = new Dataset(junkImage);
		}
		
		if (in.isFloat())
		{
			setAlgorithm(new SetToNaN(in, loThreshold, hiThreshold));
			super.run();
		}
	}
	
	// ********** private interface ****************************************************************
	
	/** provate implementation of algorithm */
	private class SetToNaN implements OutputAlgorithm<T>
	{
		private Image<T> inputImage;
		private Image<T> outputImage;
		private double loThreshold;
		private double hiThreshold;
		
		public SetToNaN(Dataset in, double loThreshold, double hiThreshold)
		{
			inputImage = (Image<T>) in.getImage();  // TODO - failure is a real possibility here (example: pass Image<FloatType> when declared plugin of DoubleType
			outputImage = inputImage.createNewImage();
			this.loThreshold = loThreshold;
			this.hiThreshold = hiThreshold;
		}
		
		@Override
		public boolean checkInput()
		{
			return true;
		}

		@Override
		public String getErrorMessage()
		{
			return null;
		}

		@Override
		public boolean process()
		{
			Cursor<T> inputCursor = inputImage.createCursor();
			Cursor<T> outputCursor = outputImage.createCursor();
			
			while (inputCursor.hasNext() && outputCursor.hasNext())
			{
				T input = inputCursor.next();
				T output = outputCursor.next();
				
				double inputValue = input.getRealDouble();
				
				if ((inputValue < loThreshold) || (inputValue > hiThreshold))
					output.setReal(Double.NaN);
				else
					output.setReal(inputValue);
			}
			
			inputCursor.close();
			outputCursor.close();
			
			return true;
		}

		@Override
		public Image<T> getResult()
		{
			return outputImage;
		}
		
	}
	
	/** create an image of given type and dimensions using specified container type */
	private static <K extends RealType<K>> Image<K> createImage(RealType<K> type, int[] dimensions)
	{
		PlanarContainerFactory cFact = new PlanarContainerFactory();
		ImageFactory<K> factory = new ImageFactory<K>((K)type, cFact);
		return factory.createImage(dimensions);
	}
}

@@ -1209,28 +1209,45 @@
 Image = 
-create
+Dataset.createPlanar
 Image(
+%22%22,
 new Floa
@@ -3050,365 +3050,6 @@
 %0A%09%7D%0A
-%09%0A%09/** create an image of given type and dimensions using specified container type */%0A%09private static %3CK extends RealType%3CK%3E%3E Image%3CK%3E createImage(RealType%3CK%3E type, int%5B%5D dimensions)%0A%09%7B%0A%09%09PlanarContainerFactory cFact = new PlanarContainerFactory();%0A%09%09ImageFactory%3CK%3E factory = new ImageFactory%3CK%3E((K)type, cFact);%0A%09%09return factory.createImage(dimensions);%0A%09%7D%0A
 %7D%0A

remove private method for creating a temporary Image and call its cousin located in Dataset