package ij.macro;
import ij.*;
import ij.plugin.*;
import ij.plugin.frame.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Hashtable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;

/** This class implements the text editor's Macros/Find Functions command.
It was written by jerome.mutterer at ibmp.fr, and is based on Mark Longair's CommandFinder plugin.
*/

public class FunctionFinder implements TextListener,  WindowListener, KeyListener, ItemListener {
    Dialog d;
    TextField prompt;
    List completions;
    String [] commands ;
    
    public FunctionFinder() {
        String exists = IJ.runMacro("return File.exists(getDirectory('macros')+'functions.html');");
        if (exists=="0")	{
            String installLocalMacroFunctionsFile = "functions = File.openUrlAsString('"+IJ.URL+"/developer/macro/functions.html');\n"+
                    "f = File.open(getDirectory('macros')+'functions.html');\n"+
                    "print (f, functions);\n"+
                    "File.close(f);";
            try { IJ.runMacro(installLocalMacroFunctionsFile);
            } catch (Throwable e) { IJ.error("Problem downloading functions.html"); return;}
        }
        String f = IJ.runMacro("return File.openAsString(getDirectory('macros')+'functions.html');");
        String [] l = f.split("\n");
        commands= new String [l.length];
        int c=0;
        for (int i=0; i<l.length; i++) {
            String line = l[i];
            if (line.startsWith("<b>")) {
                commands[c]=line.substring(line.indexOf("<b>")+3,line.indexOf("</b>"));
                c++;
            }
        }
        if (c==0) {
        	IJ.error("ImageJ/macros/functions.html is corrupted");
        	return;
        }
        
        ImageJ imageJ = IJ.getInstance();
        d = new Dialog(imageJ, "Built-in Functions");
        d.setLayout(new BorderLayout());
        d.addWindowListener(this);
        Panel northPanel = new Panel();
        prompt = new TextField("", 30);
        prompt.addTextListener(this);
        prompt.addKeyListener(this);
        northPanel.add(prompt);
        d.add(northPanel, BorderLayout.NORTH);
        completions = new List(12);
        completions.addKeyListener(this);
        populateList("");
        d.add(completions, BorderLayout.CENTER);
        d.pack();
        
        Frame frame = WindowManager.getFrontWindow();
        if (frame==null) return;
        java.awt.Point posi=frame.getLocationOnScreen();
        int initialX = (int)posi.getX() + 38;
        int initialY = (int)posi.getY() + 84;
        d.setLocation(initialX,initialY);
        d.setVisible(true);
        d.toFront();
    }

    public void populateList(String matchingSubstring) {
        String substring = matchingSubstring.toLowerCase();
        completions.removeAll();
        try {
            for(int i=0; i<commands.length; ++i) {
                String commandName = commands[i];
                if (commandName.length()==0)
                    continue;
                String lowerCommandName = commandName.toLowerCase();
                if( lowerCommandName.indexOf(substring) >= 0 ) {
                    completions.add(commands[i]);
                }
            }
        } catch (Exception e){}
    }
    
    public void edPaste(String arg) {
        Frame frame = WindowManager.getFrontWindow();
        try {
            TextArea ta = ((Editor)frame).getTextArea();
            int start = ta.getSelectionStart( );
            int end = ta.getSelectionEnd( );
            try {
                ta.replaceRange(arg.substring(0,arg.length()), start, end);
            } catch (Exception e) { }
            if (IJ.isMacOSX())
                ta.setCaretPosition(start+arg.length());
        } catch (Exception e) { }
        
    }
    public void itemStateChanged(ItemEvent ie) {
        populateList(prompt.getText());
    }
    
    protected void runFromLabel(String listLabel) {
        edPaste(listLabel);
        d.dispose();
    }
    
    public void keyPressed(KeyEvent ke) {
        int key = ke.getKeyCode();
        int items = completions.getItemCount();
        Object source = ke.getSource();
        if (source==prompt) {
            if (key==KeyEvent.VK_ENTER) {
                if (1==items) {
                    String selected = completions.getItem(0);
                    runFromLabel(selected);
                }
            } else if (key==KeyEvent.VK_UP) {
                completions.requestFocus();
                if(items>0)
                    completions.select(completions.getItemCount()-1);
            } else if (key==KeyEvent.VK_ESCAPE) {
                d.dispose();
            } else if (key==KeyEvent.VK_DOWN)  {
                completions.requestFocus();
                if (items>0)
                    completions.select(0);
            }
        } else if (source==completions) {
            if (key==KeyEvent.VK_ENTER) {
                String selected = completions.getSelectedItem();
                if (selected!=null)
                    runFromLabel(selected);
            }
        }
    }
    
    public void keyReleased(KeyEvent ke) { }
    
    public void keyTyped(KeyEvent ke) { }
    
    public void textValueChanged(TextEvent te) {
        populateList(prompt.getText());
    }
        
    public void windowClosing(WindowEvent e) {
        d.dispose();
    }
    
    public void windowActivated(WindowEvent e) { }
    public void windowDeactivated(WindowEvent e) { }
    public void windowClosed(WindowEvent e) { }
    public void windowOpened(WindowEvent e) { }
    public void windowIconified(WindowEvent e) { }
    public void windowDeiconified(WindowEvent e) { }
}

