package ij.plugin;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.plugin.filter.Analyzer;
import ij.measure.Measurements;
import java.awt.*;
import java.awt.event.*;
import java.util.*;


/** This plugin implements the Edit/Options/Point Tool command. */
public class PointToolOptions implements PlugIn, DialogListener {
	private static GenericDialog gd = null;
	private boolean multipointTool;
	private boolean isMacro;

	public static final String help = "<html>"
	+"<h1>Point Tool</h1>"
	+"<font size=+1>"
	+"<ul>"
	+"<li> Click on a point and drag to move it.<br>"
	+"<li> Alt-click, or control-click, on a point to delete it.<br>"
	+"<li> To delete multiple points, create an area<br>selection while holding down the alt key.<br>"
	+"<li> Press 'alt+y' (<i>Edit&gt;Selection&gt;Properties</i> plus<br>alt key) to display the counts in a results table.<br>"
	+"<li> Press 'm' (<i>Analyze&gt;Measure</i>) to list the counter<br>and stack position associated with each point.<br>"
	+"<li> To measure a subset of the points, move them<br>to an overlay, create a selection and then use<br><i>Image&gt;Overlay&gt;Measure Overlay</i>.<br>"
	+"<li> Use <i>File&gt;Save As&gt;Tiff</i> or <i>File&gt;Save As&gt;Selection</i><br>to save the points and counts.<br>"
	+"<li> Press 'F' (<i>Image&gt;Overlay</i>&gt;Flatten</i>) to create an<br>RGB image with embedded markers for export.<br>"
	+"<li> Hold the shift key down and points will be<br>constrained to a horizontal or vertical line.<br>"
	+"<li> Use <i>Edit&gt;Selection&gt;Select None</i> to delete a<br>multi-point selection.<br>"
	+"<li> Switch to the multi-point tool and use<br><i>Edit&gt;Selection&gt;Restore Selection</i> to restore<br>a deleted multi-point selection.<br>"
	+"</ul>"
	+" <br>"
	+"</font>";

 	public void run(String arg) {
 		if (gd!=null && gd.isShowing() && !IJ.isMacro()) {
 			gd.toFront();
 			update();
 		} else
 			showDialog();
 	}

	void showDialog() {
		String options = IJ.isMacro()?Macro.getOptions():null;
		isMacro = options!=null;
		boolean legacyMacro = false;
		if (isMacro) {
			options = options.replace("selection=", "color=");
			options = options.replace("marker=", "size=");
			options = options.replace("type=Crosshair", "type=Cross");
			Macro.setOptions(options);
			legacyMacro = options.contains("auto-") || options.contains("add");
		}
		multipointTool = Toolbar.getMultiPointMode() && !legacyMacro;
		if (isMacro && !legacyMacro)
			multipointTool = true;
		Color sc =Roi.getColor();
		String sname = Colors.getColorName(sc, "Yellow");
		Color cc =PointRoi.getDefaultCrossColor();
		String cname = Colors.getColorName(cc, "None");
		String type = PointRoi.types[PointRoi.getDefaultType()];
		String size = PointRoi.sizes[PointRoi.getDefaultSize()];
		gd = GUI.newNonBlockingDialog("Point Tool");
		gd.setInsets(5,0,2);
		gd.addChoice("Type:", PointRoi.types, type);
		gd.addChoice("Color:", Colors.getColors(), sname);
		gd.addChoice("Size:", PointRoi.sizes, size);
		if (!multipointTool) {
			gd.addCheckbox("Auto-measure", Prefs.pointAutoMeasure);
			gd.addCheckbox("Auto-next slice", Prefs.pointAutoNextSlice);
			gd.addCheckbox("Add_to overlay", Prefs.pointAddToOverlay);
			gd.addCheckbox("Add to ROI Manager", Prefs.pointAddToManager);
		}
		gd.setInsets(5, 20, 0);
		gd.addCheckbox("Label points", !Prefs.noPointLabels);
		gd.addCheckbox("Show on all slices", Prefs.showAllPoints);
		if (multipointTool) {
			gd.setInsets(15,0,5);
			String[] choices =  PointRoi.getCounterChoices();
			gd.addChoice("Counter:", choices, choices[getCounter()]);
			gd.setInsets(2, 75, 0);
			gd.addMessage(getCount(getCounter())+"    ");
		}
		gd.addHelp(help);
		gd.addDialogListener(this);
		gd.showDialog();
	}

	public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
		boolean redraw = false;
		// type
		int typeIndex = gd.getNextChoiceIndex();
		if (typeIndex!=PointRoi.getDefaultType()) {
			PointRoi.setDefaultType(typeIndex);
			redraw = true;
		}
		// color
		String selectionColor = gd.getNextChoice();
		Color sc = Colors.getColor(selectionColor, Color.yellow);
		if (sc!=Roi.getColor()) {
			Roi.setColor(sc);
			redraw = true;
			Toolbar tb = Toolbar.getInstance();
			if (tb!=null) tb.repaint();
		}
		// size
		int sizeIndex = gd.getNextChoiceIndex();
		if (sizeIndex!=PointRoi.getDefaultSize()) {
			PointRoi.setDefaultSize(sizeIndex);
			redraw = true;
		}
		if (!multipointTool) {
			Prefs.pointAutoMeasure = gd.getNextBoolean();
			Prefs.pointAutoNextSlice = gd.getNextBoolean();
			Prefs.pointAddToOverlay = gd.getNextBoolean();
			Prefs.pointAddToManager = gd.getNextBoolean();
			if (Prefs.pointAddToOverlay)
				Prefs.pointAddToManager = false;
			if (Prefs.pointAutoNextSlice&&!Prefs.pointAddToManager)
				Prefs.pointAutoMeasure = true;
		}
		boolean updateLabels = false;
		boolean noPointLabels = !gd.getNextBoolean();
		if (noPointLabels!=Prefs.noPointLabels) {
			redraw = true;
			updateLabels = true;
		}
		Prefs.noPointLabels = noPointLabels;
		boolean showAllPoints = gd.getNextBoolean();
		if (showAllPoints!=Prefs.showAllPoints)
			redraw = true;
		Prefs.showAllPoints = showAllPoints;
		if (multipointTool) {
			int counter = gd.getNextChoiceIndex();
			if (counter==0 || counter!=getCounter()) {
				setCounter(counter);
				redraw = true;
			}
		}
		if (isMacro) {
			PointRoi roi = getPointRoi();
			if (roi!=null) {
				roi.setPointType(typeIndex);
				roi.setStrokeColor(sc);
				roi.setSize(sizeIndex);
				redraw = true;
			}
		}
		if (redraw) {
			ImagePlus imp = null;
			boolean impHasPointRoi = false;
			PointRoi roi = getPointRoi();
			if (roi!=null) {
				roi.setShowLabels(!Prefs.noPointLabels);
				imp = roi.getImage();
				impHasPointRoi = true;
			}
			if (updateLabels) {
				imp = WindowManager.getCurrentImage();
				Overlay overlay = imp!=null?imp.getOverlay():null;
				if (overlay!=null) {
					for (int i=0; i<overlay.size(); i++) {
						Roi r = overlay.get(i);
						roi = r!=null && (r instanceof PointRoi)?(PointRoi)r:null;
						if (roi!=null) {
							roi.setShowLabels(!Prefs.noPointLabels);
							impHasPointRoi = true;
						}
					}
				}
			}
			if (imp!=null && impHasPointRoi)
				imp.draw();
		}
		return true;
    }

    private static int getCounter() {
     	PointRoi roi = getPointRoi();
     	return roi!=null?roi.getCounter():0;
    }

    private static void setCounter(int counter) {
    	PointRoi roi = getPointRoi();
		if (roi!=null)
			roi.setCounter(counter);
		PointRoi.setDefaultCounter(counter);
    }

    private static PointRoi getPointRoi() {
    	ImagePlus imp = WindowManager.getCurrentImage();
    	if (imp==null)
    		return null;
		Roi roi = imp.getRoi();
		if (roi==null)
			return null;
		if (roi instanceof PointRoi)
			return (PointRoi)roi;
		else
			return null;
    }

    private static int getCount(int counter) {
     	PointRoi roi = getPointRoi();
     	return roi!=null?roi.getCount(counter):0;
    }

    public static void update() {
    	if (gd!=null && gd.isShowing()) {
			Vector choices = gd.getChoices();
			if (choices==null || choices.size()<4)
				return;
			Choice counterChoice = (Choice)choices.elementAt(3);
			int counter = getCounter();
			int count = getCount(counter);
			counterChoice.select(counter);
			((Label)gd.getMessage()).setText(""+count);
		}
    }

}
