/*
 * DefaultInputHandler.java - Default implementation of an input handler
 * Copyright (C) 1999 Slava Pestov
 *
 * You may use and modify this package for any purpose. Redistribution is
 * permitted, in both source and binary form, provided that this notice
 * remains intact in all source distributions of this package.
 */

package processing.app.syntax;

import javax.swing.KeyStroke;
import java.awt.event.*;
import java.awt.Toolkit;
import java.util.Hashtable;
import java.util.StringTokenizer;

/**
 * The default input handler. It maps sequences of keystrokes into actions
 * and inserts key typed events into the text area.
 * @author Slava Pestov
 * @version $Id: DefaultInputHandler.java 1438 2005-05-11 08:34:16Z benfry $
 */
public class DefaultInputHandler extends InputHandler
{
        /**
         * Creates a new input handler with no key bindings defined.
         */
        public DefaultInputHandler()
        {
                bindings = currentBindings = new Hashtable();
        }

        /**
         * Sets up the default key bindings.
         */
        public void addDefaultKeyBindings()
        {
                addKeyBinding("BACK_SPACE",BACKSPACE);
                addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD);
                addKeyBinding("DELETE",DELETE);
                addKeyBinding("C+DELETE",DELETE_WORD);

                addKeyBinding("ENTER",INSERT_BREAK);
                addKeyBinding("TAB",INSERT_TAB);

                addKeyBinding("INSERT",OVERWRITE);
                addKeyBinding("C+\\",TOGGLE_RECT);

                addKeyBinding("HOME",HOME);
                addKeyBinding("END",END);
                addKeyBinding("S+HOME",SELECT_HOME);
                addKeyBinding("S+END",SELECT_END);
                addKeyBinding("C+HOME",DOCUMENT_HOME);
                addKeyBinding("C+END",DOCUMENT_END);
                addKeyBinding("CS+HOME",SELECT_DOC_HOME);
                addKeyBinding("CS+END",SELECT_DOC_END);

                addKeyBinding("PAGE_UP",PREV_PAGE);
                addKeyBinding("PAGE_DOWN",NEXT_PAGE);
                addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE);
                addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE);

                addKeyBinding("LEFT",PREV_CHAR);
                addKeyBinding("S+LEFT",SELECT_PREV_CHAR);
                addKeyBinding("C+LEFT",PREV_WORD);
                addKeyBinding("CS+LEFT",SELECT_PREV_WORD);
                addKeyBinding("RIGHT",NEXT_CHAR);
                addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR);
                addKeyBinding("C+RIGHT",NEXT_WORD);
                addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD);
                addKeyBinding("UP",PREV_LINE);
                addKeyBinding("S+UP",SELECT_PREV_LINE);
                addKeyBinding("DOWN",NEXT_LINE);
                addKeyBinding("S+DOWN",SELECT_NEXT_LINE);

                addKeyBinding("C+ENTER",REPEAT);
        }

        /**
         * Adds a key binding to this input handler. The key binding is
         * a list of white space separated key strokes of the form
         * <i>[modifiers+]key</i> where modifier is C for Control, A for Alt,
         * or S for Shift, and key is either a character (a-z) or a field
         * name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE)
         * @param keyBinding The key binding
         * @param action The action
         */
        public void addKeyBinding(String keyBinding, ActionListener action)
        {
                Hashtable current = bindings;

                StringTokenizer st = new StringTokenizer(keyBinding);
                while(st.hasMoreTokens())
                {
                        KeyStroke keyStroke = parseKeyStroke(st.nextToken());
                        if(keyStroke == null)
                                return;

                        if(st.hasMoreTokens())
                        {
                                Object o = current.get(keyStroke);
                                if(o instanceof Hashtable)
                                        current = (Hashtable)o;
                                else
                                {
                                        o = new Hashtable();
                                        current.put(keyStroke,o);
                                        current = (Hashtable)o;
                                }
                        }
                        else
                                current.put(keyStroke,action);
                }
        }

        /**
         * Removes a key binding from this input handler. This is not yet
         * implemented.
         * @param keyBinding The key binding
         */
        public void removeKeyBinding(String keyBinding)
        {
                throw new InternalError("Not yet implemented");
        }

        /**
         * Removes all key bindings from this input handler.
         */
        public void removeAllKeyBindings()
        {
                bindings.clear();
        }

        /**
         * Returns a copy of this input handler that shares the same
         * key bindings. Setting key bindings in the copy will also
         * set them in the original.
         */
        public InputHandler copy()
        {
                return new DefaultInputHandler(this);
        }

        /**
         * Handle a key pressed event. This will look up the binding for
         * the key stroke and execute it.
         */
        public void keyPressed(KeyEvent evt)
        {
          int keyCode = evt.getKeyCode();
          int modifiers = evt.getModifiers();

          // moved this earlier so it doesn't get random meta clicks
          if (keyCode == KeyEvent.VK_CONTROL ||
              keyCode == KeyEvent.VK_SHIFT ||
              keyCode == KeyEvent.VK_ALT ||
              keyCode == KeyEvent.VK_META) {
            return;
          }

          // don't get command-s or other menu key equivs on mac
          // unless it's something that's specifically bound (cmd-left or right)
          //if ((modifiers & KeyEvent.META_MASK) != 0) return;
          if ((modifiers & KeyEvent.META_MASK) != 0) {
            KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, modifiers);
            if (currentBindings.get(keyStroke) == null) {
              return;
            }
          }

                /*
                char keyChar = evt.getKeyChar();
                System.out.println("code=" + keyCode + " char=" + keyChar +
                                   " charint=" + ((int)keyChar));
                System.out.println("other codes " + KeyEvent.VK_ALT + " " +
                                   KeyEvent.VK_META);
                */

                if((modifiers & ~KeyEvent.SHIFT_MASK) != 0
                        || evt.isActionKey()
                        || keyCode == KeyEvent.VK_BACK_SPACE
                        || keyCode == KeyEvent.VK_DELETE
                        || keyCode == KeyEvent.VK_ENTER
                        || keyCode == KeyEvent.VK_TAB
                        || keyCode == KeyEvent.VK_ESCAPE)
                {
                        if(grabAction != null)
                        {
                                handleGrabAction(evt);
                                return;
                        }

                        KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode,
                                modifiers);
                        Object o = currentBindings.get(keyStroke);
                        if(o == null)
                        {
                                // Don't beep if the user presses some
                                // key we don't know about unless a
                                // prefix is active. Otherwise it will
                                // beep when caps lock is pressed, etc.
                                if(currentBindings != bindings)
                                {
                                        Toolkit.getDefaultToolkit().beep();
                                        // F10 should be passed on, but C+e F10
                                        // shouldn't
                                        repeatCount = 0;
                                        repeat = false;
                                        evt.consume();
                                }
                                currentBindings = bindings;
                                return;
                        }
                        else if(o instanceof ActionListener)
                        {
                                currentBindings = bindings;

                                executeAction(((ActionListener)o),
                                        evt.getSource(),null);

                                evt.consume();
                                return;
                        }
                        else if(o instanceof Hashtable)
                        {
                                currentBindings = (Hashtable)o;
                                evt.consume();
                                return;
                        }
                }
        }

        /**
         * Handle a key typed event. This inserts the key into the text area.
         */
        public void keyTyped(KeyEvent evt)
        {
                int modifiers = evt.getModifiers();
                char c = evt.getKeyChar();

                // this is the apple/cmd key on macosx.. so menu commands
                // were being passed through as legit keys.. added this line
                // in an attempt to prevent.
                if ((modifiers & KeyEvent.META_MASK) != 0) return;

                if (c != KeyEvent.CHAR_UNDEFINED) // &&
                  //                (modifiers & KeyEvent.ALT_MASK) == 0)
                {
                  if(c >= 0x20 && c != 0x7f)
                        {
                                KeyStroke keyStroke = KeyStroke.getKeyStroke(
                                        Character.toUpperCase(c));
                                Object o = currentBindings.get(keyStroke);

                                if(o instanceof Hashtable)
                                {
                                        currentBindings = (Hashtable)o;
                                        return;
                                }
                                else if(o instanceof ActionListener)
                                {
                                        currentBindings = bindings;
                                        executeAction((ActionListener)o,
                                                evt.getSource(),
                                                String.valueOf(c));
                                        return;
                                }

                                currentBindings = bindings;

                                if(grabAction != null)
                                {
                                        handleGrabAction(evt);
                                        return;
                                }

                                // 0-9 adds another 'digit' to the repeat number
                                if(repeat && Character.isDigit(c))
                                {
                                        repeatCount *= 10;
                                        repeatCount += (c - '0');
                                        return;
                                }

                                executeAction(INSERT_CHAR,evt.getSource(),
                                        String.valueOf(evt.getKeyChar()));

                                repeatCount = 0;
                                repeat = false;
                        }
                }
        }

        /**
         * Converts a string to a keystroke. The string should be of the
         * form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i>
         * is any combination of A for Alt, C for Control, S for Shift
         * or M for Meta, and <i>shortcut</i> is either a single character,
         * or a keycode name from the <code>KeyEvent</code> class, without
         * the <code>VK_</code> prefix.
         * @param keyStroke A string description of the key stroke
         */
        public static KeyStroke parseKeyStroke(String keyStroke)
        {
                if(keyStroke == null)
                        return null;
                int modifiers = 0;
                int index = keyStroke.indexOf('+');
                if(index != -1)
                {
                        for(int i = 0; i < index; i++)
                        {
                                switch(Character.toUpperCase(keyStroke
                                        .charAt(i)))
                                {
                                case 'A':
                                        modifiers |= InputEvent.ALT_MASK;
                                        break;
                                case 'C':
                                        modifiers |= InputEvent.CTRL_MASK;
                                        break;
                                case 'M':
                                        modifiers |= InputEvent.META_MASK;
                                        break;
                                case 'S':
                                        modifiers |= InputEvent.SHIFT_MASK;
                                        break;
                                }
                        }
                }
                String key = keyStroke.substring(index + 1);
                if(key.length() == 1)
                {
                        char ch = Character.toUpperCase(key.charAt(0));
                        if(modifiers == 0)
                                return KeyStroke.getKeyStroke(ch);
                        else
                                return KeyStroke.getKeyStroke(ch,modifiers);
                }
                else if(key.length() == 0)
                {
                        System.err.println("Invalid key stroke: " + keyStroke);
                        return null;
                }
                else
                {
                        int ch;

                        try
                        {
                                ch = KeyEvent.class.getField("VK_".concat(key))
                                        .getInt(null);
                        }
                        catch(Exception e)
                        {
                                System.err.println("Invalid key stroke: "
                                        + keyStroke);
                                return null;
                        }

                        return KeyStroke.getKeyStroke(ch,modifiers);
                }
        }

        // private members
        private Hashtable bindings;
        private Hashtable currentBindings;

        private DefaultInputHandler(DefaultInputHandler copy)
        {
                bindings = currentBindings = copy.bindings;
        }
}
