package ij.plugin.frame;
import ij.*;
import ij.gui.*;
import java.awt.*;
import java.awt.event.*;


/** This plugin implements the Plugins>Utiltiees>Recent Commands command. */
public class Commands extends PlugInFrame implements ActionListener, ItemListener, CommandListener {
	public static final String LOC_KEY = "commands.loc";
	public static final String CMDS_KEY = "commands.cmds";
		public static final int MAX_COMMANDS = 20;
	private static Frame instance;
	private static final String divider = "---------------";
	private static final String[] commands = {
		"Blobs",
		"Open...",
		"Show Info...",
		"Close",
		"Close All",
		"Appearance...",
		"Histogram",
		"Gaussian Blur...",		
		"Record...",
		"Capture Screen",
		"Find Commands..."
	};
	private List list;
	private String command;
	private Button button;

	public Commands() {
		super("Commands");
		if (instance!=null) {
			WindowManager.toFront(instance);
			return;
		}
		instance = this;
		WindowManager.addWindow(this);
		list = new List(MAX_COMMANDS);
		list.addItemListener(this);
		String cmds = Prefs.get(CMDS_KEY, null);
		if (cmds!=null) {
			String[] cmd = cmds.split(",");
			int len = cmd.length<=MAX_COMMANDS?cmd.length:MAX_COMMANDS;
			boolean isDivider = false;
			for (int i=0; i<len; i++) {
				if (divider.equals(cmd[i])) {
					isDivider = true;
					break;
				}
			}
			if (isDivider) {
				for (int i=0; i<len; i++)
					list.add(cmd[i]);
			} else
				cmds = null;				
		}
		if (cmds==null)
			reset();
		ImageJ ij = IJ.getInstance();
		addKeyListener(ij);
		Executer.addCommandListener(this);
		GUI.scale(list);
		list.addKeyListener(ij);
		GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        setLayout(gridbag);
        c.insets = new Insets(0, 0, 0, 0); 
        c.gridx = 0; c.gridy = 0; c.anchor = GridBagConstraints.WEST;
        add(list,c); 
		button = new Button("Edit");
		button.addActionListener(this);
		button.addKeyListener(ij);
        //c.insets = new Insets(2, 6, 6, 6); 
        c.gridx = 0; c.gridy = 2; c.anchor = GridBagConstraints.CENTER;
        add(button, c);
		pack();
		Dimension size = getSize();
		Point loc = Prefs.getLocation(LOC_KEY);
		if (loc!=null)
			setLocation(loc);
		show();
	}

	public void actionPerformed(ActionEvent e) {
		GenericDialog gd = new GenericDialog("Commands");
		int dividerIndex = getDividerIndex();
		StringBuilder sb = new StringBuilder(200);
		sb.append("| ");	
		for (int i=0; i<dividerIndex; i++) {
			String cmd = list.getItem(i);
			sb.append(cmd);
			sb.append(" | ");
		}
		sb.append("Debug Mode | Hyperstack |");
		String recentCommands = sb.toString();
		gd.setInsets(5, 0, 0);
		gd.addTextAreas(recentCommands, null, 5, 28);
		int index = dividerIndex + 1;
		int n = 1;
		for (int i=index; i<list.getItemCount(); i++) {
			gd.setInsets(2, 8, 0);
			gd.addStringField("Cmd"+IJ.pad(n++,2)+":", list.getItem(i), 20);
		}
		gd.enableYesNoCancel(" OK ", "Reset");
		gd.showDialog();
		if (gd.wasCanceled())
			return;
		else if (!gd.wasOKed()) {
			boolean ok = IJ.showMessageWithCancel("Commands", "Are you sure you want to reset?");
			if (ok) reset();
        } else { 
			for (int i=index; i<list.getItemCount(); i++)
				list.replaceItem(gd.getNextString(),i);
		}
	}

	public void itemStateChanged(ItemEvent e) {
		//IJ.log("itemStateChanged: "+e);
		if (e.getStateChange()==ItemEvent.SELECTED) {
			int index = list.getSelectedIndex();
			if (index<0)
				return;
			command = list.getItem(index);
			if (!command.equals(divider)) {
				if (command.equals("Debug Mode"))
					IJ.runMacro("setOption('DebugMode')");
				else if (command.equals("Hyperstack"))
					IJ.runMacro("newImage('HyperStack', '8-bit color label', 400, 300, 3, 4, 25)");
				else
					IJ.doCommand(command);
			}
			list.deselect(index);
		}
	}
	
	public String commandExecuting(String cmd2) {
		if ("Quit".equals(cmd2))
			return cmd2;
		String cmd1 = command;
		if (cmd1==null || !cmd1.equals(cmd2)) {
			try {
				list.remove(cmd2);
			} catch(Exception e) {}
			if (list.getItemCount()>=MAX_COMMANDS)
				list.remove(getDividerIndex()-1);
			list.add(cmd2, 0);
		}
		command = null;
		return cmd2;
	}
	
	private int getDividerIndex() {
		int index = 0;
		for (int i=0; i<MAX_COMMANDS; i++) {
			String cmd = list.getItem(i);
			if (divider.equals(cmd)) {
				index = i;
				break;
			}
		}
		return index;
	}
	
	private void reset() {
		list.clear();
		list.add(divider);
		int len = commands.length<MAX_COMMANDS?commands.length:MAX_COMMANDS-1;
		for (int i=0; i<len; i++)
			list.add(commands[i]);		
	}
	
	/** Overrides PlugInFrame.close(). */
	public void close() {
		super.close();
		instance = null;
		Executer.removeCommandListener(this);
		Prefs.saveLocation(LOC_KEY, getLocation());
		StringBuilder sb = new StringBuilder(200);
		for (int i=0; i<list.getItemCount(); i++) {
			String cmd = list.getItem(i);
			sb.append(cmd);
			sb.append(",");
		}
		String cmds = sb.toString();
		cmds = cmds.substring(0, cmds.length()-1);
		//IJ.log("close: "+cmds); IJ.wait(5000);
		Prefs.set(CMDS_KEY, cmds);
	}

}
