import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.filter.*;
import java.io.*;
import java.util.GregorianCalendar;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;


public class Resize_Roi implements PlugInFilter, ChangeListener {
	private ImagePlus imp;
	private GenericDialog gd;
	private String[] interpolationMethods =  {"Nearest Neighbour", "Bilinear", "Bicubic"};
	Rectangle roiRect;	
	private String dir, name, shortname;
	private JSlider Width,Height;
	private JLabel pixel_w, pixel_h;
	private JSpinner spinner_w, spinner_h; 
	private int value_w, value_h;
	
	public int setup(String arg, ImagePlus imp) {
		if(arg.equals("about")){
			showAbout();
			return DONE;
		}
		return DOES_ALL;
	}
	
	public void run(ImageProcessor ip) {
		roiRect=ip.getRoi(); 
		
		//Name and Directory of the current image
		shortname=IJ.getImage().getShortTitle();
		name= IJ.getImage().getTitle();
		dir = IJ.getDirectory("image");
		
		IJ.showStatus("Resize: region of interest with "+roiRect.width+"x"+roiRect.height);
		
		initialize();
       	if (gd.wasCanceled()) return;  //if you press cancel must not anything
		
		String item= gd.getNextChoice();
		boolean report= gd.getNextBoolean();

		// Creates a new ImageProcessor containing an image that corresponds to the current ROI.
		ImageProcessor roi_ip=ip.crop(); 
		resizeImage(roi_ip, getMethodInterpolation(item));

		if(report)
			makeReport(item);
	}

	private void initialize() {
		gd = new GenericDialog("Insert the input");
		Panel panel_w=new Panel(); 
		Panel panel_h=new Panel();
		Panel panel=new Panel();
		Panel panel2=new Panel();
		Float x=(float)1/(float)roiRect.width;
		Float y=(float)1/(float)roiRect.height;

		JLabel factor_w=new JLabel("Scale ");
		JLabel factor_h=new JLabel("Scale ");

		JLabel label_w =new JLabel("Width: ");
		JLabel label_h =new JLabel("Height: ");
		
		Width = new JSlider(JSlider.HORIZONTAL,1,4*roiRect.width, roiRect.width); 
		Height =new JSlider(JSlider.HORIZONTAL,1,4*roiRect.height, roiRect.height);
		Width.addChangeListener(this);
		Height.addChangeListener(this);
		
		SpinnerModel w=new SpinnerNumberModel(new Float(1F), new Float(x), new Float(4F), new Float(0.1F));
		spinner_w=new JSpinner(w);		
		SpinnerModel h=new SpinnerNumberModel(new Float(1F), new Float(y), new Float(4F), new Float(0.1F));  
		spinner_h=new JSpinner(h);
		
		spinner_w.addChangeListener(new SpinnerChange()); 
		spinner_h.addChangeListener(new SpinnerChange());
		
		gd.addChoice("Interpolation method: ", interpolationMethods , interpolationMethods[0]); 
		
		pixel_w=new JLabel(Integer.toString(Width.getValue())+"  pixelsXwidth");
		pixel_h=new JLabel(Integer.toString(Height.getValue())+"  pixelsXheight");
		
		panel_w.add(label_w);
		panel.add(factor_w);
		panel.add(spinner_w);
		panel.add(Width);
		panel.add(pixel_w);
		
		panel_h.add(label_h);
		panel2.add(factor_h);
		panel2.add(spinner_h);
		panel2.add(Height);
		panel2.add(pixel_h);
		
		gd.addPanel(panel_w);
		gd.addPanel(panel);
		gd.addPanel(panel_h);
		gd.addPanel(panel2);

		value_w =  Width.getValue();
		value_h = Height.getValue();
		
		gd.addCheckbox("Print report", true); 
		
		gd.showDialog();
	}

	private void resizeImage(ImageProcessor roi_ip, int interpolation) {

		roi_ip.setInterpolationMethod(interpolation);
		
		ImageProcessor roiResize_ip=roi_ip.resize(value_w, value_h); 
		// Creates a new ImageProcessor containing a scaled copy of this image or ROI
		
		ImagePlus roiResize=NewImage.createRGBImage("Resize of Roi", roiRect.width, roiRect.height, 1, NewImage.FILL_BLACK);
		roiResize.setProcessor("zooming",roiResize_ip);
	
		ImageWindow imw=new ImageWindow(roiResize);
		imw.setVisible(true); 
	}

	private int getMethodInterpolation(String item) {
		if (item.equals(interpolationMethods[1]))
			return 1;
		else if (item.equals(interpolationMethods[2]))
			return 2;
		return 0;
	}

	private void makeReport(String method) {
		
		GregorianCalendar calendar = new GregorianCalendar();
		
		String user= System.getProperty("user.name");

		String report= "<html><Head> <title>Report </title></head><body><h1>ImageJ Report</h1>Report Generation: "+ calendar.getTime()+"<br />User: "+user+" <BR>File: "+dir+name+" <BR> <BR><h3> Ridimensiona</h3><h4>Dettagli:</h4><ul>\"Ridimensiona\" interpola l'immagine in ingresso generando in uscita un\'immagine delle dimensioni desiderate.<BR>Gli algoritmi d\'interpolazione disponibili sono:<BR>- \"Nearest\": copia semplicemente il valore del pixel pi&ugrave vicino alla posizione da interpolare;<BR>- \"Bilineare\": usa un\'interpolazaione bilineare per ricampionare i dati;<br /> - \"Bicubica\": usa un\'interpolazaione bicubica per ricampionare i dati;</ul><h4>Parametri: </h4> Il filtro &egrave stato applicato ad una regione avente coordinate in alto a sinistra: ( "+roiRect.x+ ", " +roiRect.y+" ), Width: "+roiRect.width+", Height: "+roiRect.height+"<ul><li><b>Width: </b>"+value_w+" pixelsXwidth , scale factor: "+ (float)value_w/roiRect.width+ "</li><br /><i>Larghezza della nuova immagine.</i><br /><br /><li><b>Height: </b>"+value_h+" pixelsXheight  , scale factor: "+ (float)value_h/roiRect.height+ "</li><br /><i>Altezza della nuova immagine.</i><br /><br /><li><b>Interpolation: </b>"+method+"</li><br /><i>Tipo di interpolazione.</i><br /><br /></body></html>";
		
		try{ 
			//Creates a new file (.htlm) containing of the information filter applied
			PrintWriter pw=new PrintWriter(new BufferedWriter (new FileWriter(dir+shortname+".html")));
			pw.print(report);
        	pw.close();
		}
		catch (Exception e) {}
	}
	
	public void stateChanged(ChangeEvent e){
		Object source = e.getSource();
		if (source==Width) {
			value_w = Width.getValue();
			pixel_w.setText(Integer.toString(value_w) +"  pixelsXwidth");
			spinner_w.setValue((float)value_w/roiRect.width);	
		}
		else if (source==Height) {
			value_h=Height.getValue();
			pixel_h.setText(Integer.toString(value_h) +"  pixelsXheight");
			spinner_h.setValue((float)value_h/roiRect.height);
		}	
	}
		
	// Invokes the static method of IJ showMessage() to display a message, the first parameter is the title and the seconda parameter is the text.
	void showAbout() {
		IJ.showMessage("About Resize_Filter...", "this filters make the resize of the input image");
	}
	
	class SpinnerChange implements ChangeListener{
		public void stateChanged(ChangeEvent e) {
			Object source = e.getSource();
			if (source==spinner_w){
				value_w=(int)((Float.parseFloat(spinner_w.getValue().toString()))*roiRect.width);
				Width.setValue(value_w);
			}
			else if(source == spinner_h){
				value_h=(int)((Float.parseFloat(spinner_h.getValue().toString()))*roiRect.height);
				Height.setValue(value_h);
			}
		}
	}
}
