package ij.plugin;
import ij.*;
import ij.gui.*;
import ij.io.*;
import ij.util.*;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;

/** Implements the Plugins/Shortcuts/Install... command. */
public class Installer implements PlugIn {

	private static String[] menus = {"Shortcuts", "Plugins", "Import", "Save As",
		"Filters", "Tools", "Utilities"};
	private static final String TITLE = "Installer";
	private static String command = "";
	private static String shortcut = "";
	private static String defaultPlugin = "";
	private static String menuStr = menus[0];

	public void run(String arg) {
		installPlugin();
	}

	void installPlugin() {
		String[] plugins = getPlugins();
		if (plugins==null || plugins.length==0) {
			IJ.error("No plugins found");
			return;
		}
		GenericDialog gd = new GenericDialog("Install Plugin", IJ.getInstance());
		gd.addChoice("Plugin:", plugins, defaultPlugin);
		gd.addChoice("Menu:", menus, menuStr);
		gd.addStringField("Command:", command, 16);
		gd.addStringField("Shortcut:", shortcut, 3);
		gd.addStringField("Argument:", "", 12);
		gd.showDialog();
		if (gd.wasCanceled())
			return;
		String plugin = gd.getNextChoice();
		menuStr = gd.getNextChoice();
		command = gd.getNextString();
		shortcut = gd.getNextString();
		String argument = gd.getNextString();
		IJ.register(Installer.class);
		defaultPlugin = plugin;
		if (command.equals("")) {
			IJ.showMessage(TITLE, "Command required");
			return;
		}
		if (shortcut.length()>1)
			shortcut = shortcut.replace('f','F');
		char menu = ' ';
		if (menuStr.equals(menus[0]))
			menu = Menus.SHORTCUTS_MENU;
		else if (menuStr.equals(menus[1]))
			menu = Menus.PLUGINS_MENU;
		else if (menuStr.equals(menus[2]))
			menu = Menus.IMPORT_MENU;
		else if (menuStr.equals(menus[3]))
			menu = Menus.SAVE_AS_MENU;
		else if (menuStr.equals(menus[4]))
			menu = Menus.FILTERS_MENU;
		else if (menuStr.equals(menus[5]))
			menu = Menus.TOOLS_MENU;
		else if (menuStr.equals(menus[6]))
			menu = Menus.UTILITIES_MENU;
		if (!argument.equals(""))
			plugin += "(\"" + argument +"\")";
		int err = Menus.installPlugin(plugin,menu,command,shortcut,IJ.getInstance());
		switch (err) {
			case Menus.COMMAND_IN_USE:
				IJ.showMessage(TITLE, "The command \""+command+"\" \nis already being used.");
				return;
			case Menus.INVALID_SHORTCUT:
				IJ.showMessage(TITLE, "The shortcut must be a single character or \"F1\"-\"F12\".");
				return;
			case Menus.SHORTCUT_IN_USE:
				IJ.showMessage("The \""+shortcut+"\" shortcut is already being used.");
				return;
			default:
				command = "";
				shortcut = "";
				break;
		}
		if (!plugin.endsWith(")"))
			installAbout(plugin);
	}
	
	void installAbout(String plugin) {
		boolean hasShowAboutMethod=false;
		PluginClassLoader loader = new PluginClassLoader(Menus.getPlugInsPath());
		try {
			Class c = loader.loadClass(plugin);
			Method m = c.getDeclaredMethod("showAbout", new Class[0]);
			if (m!=null)
				hasShowAboutMethod = true;
		}
		catch (Exception e) {}
		//IJ.write("installAbout: "+plugin+" "+hasShowAboutMethod);
		if (hasShowAboutMethod)
			Menus.installPlugin(plugin+"(\"about\")",Menus.ABOUT_MENU,plugin+"...","",IJ.getInstance());
	}
	
	String[] getPlugins() {
		String path = Menus.getPlugInsPath();
		if (path==null)
			return null;
		File f = new File(path);
		String[] list = f.list();
		if (list==null) return null;
		Vector v = new Vector();
		for (int i=0; i<list.length; i++) {
			String className = list[i];
			boolean isClassFile = className.endsWith(".class");
			if (className.indexOf('_')>=0 && isClassFile && className.indexOf('$')<0 ) {
				className = className.substring(0, className.length()-6); 
				v.addElement(className);
			} else {
				if (!isClassFile)
					getSubdirectoryPlugins(path, className, v);
			}
		}
		list = new String[v.size()];
		v.copyInto((String[])list);
		StringSorter.sort(list);
		return list;
	}
	
	/** Looks for plugins in a subdirectorie of the plugins directory. */
	void getSubdirectoryPlugins(String path, String dir, Vector v) {
		//IJ.write("getSubdirectoryPlugins: "+path+dir);
		if (dir.endsWith(".java"))
			return;
		File f = new File(path, dir);
		if (!f.isDirectory())
			return;
		String[] list = f.list();
		if (list==null)
			return;
		dir += "/";
		for (int i=0; i<list.length; i++) {
			String name = list[i];
			if (name.indexOf('_')>=0 && name.endsWith(".class") && name.indexOf('$')<0 ) {
				name = name.substring(0, name.length()-6); // remove ".class"
				v.addElement(name);
				//IJ.write("File: "+f+"/"+name);
			}
		}
	}

}
