/*
 *******************************************************************************
 * Copyright (C) 2004-2007, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.dev.tool.ime.translit;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.font.TextAttribute;
import java.awt.font.TextHitInfo;
import java.awt.im.InputMethodHighlight;
import java.awt.im.spi.InputMethod;
import java.awt.im.spi.InputMethodContext;
import java.text.AttributedString;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.TreeSet;

import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;

import com.ibm.icu.impl.Utility;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.ReplaceableString;
import com.ibm.icu.text.Transliterator;

public class TransliteratorInputMethod implements InputMethod {

    private static boolean usesAttachedIME() {
        // we're in the ext directory so permissions are not an issue
        String os = System.getProperty("os.name");
        if (os != null) {
            return os.indexOf("Windows") == -1;
        }
        return false;
    }

    // true if Solaris style; false if PC style, assume Apple uses PC style for now
    private static final boolean attachedStatusWindow = usesAttachedIME();

    // the shared status window
    private static Window statusWindow;

    // current or last owner
    private static TransliteratorInputMethod statusWindowOwner;

    // cache location limits for attached
    private static Rectangle attachedLimits;

    // convenience of access, to reflect the current state
    private static JComboBox choices;

    //
    // per-instance state
    //

    // if we're attached, the status window follows the client window
    private Point attachedLocation;

    private static int gid;

    private int id = gid++;

    InputMethodContext imc;
    private boolean enabled = true;

    private int selectedIndex = -1; // index in JComboBox corresponding to our transliterator
    private Transliterator transliterator;
    private int desiredContext;
    private StringBuffer buffer;
    private ReplaceableString replaceableText;
    private Transliterator.Position index;

    // debugging
    private static boolean TRACE_EVENT = false;
    private static boolean TRACE_MESSAGES = false;
    private static boolean TRACE_BUFFER = false;

    public TransliteratorInputMethod() {
        if (TRACE_MESSAGES)
            dumpStatus("<constructor>");

        buffer = new StringBuffer();
        replaceableText = new ReplaceableString(buffer);
        index = new Transliterator.Position();
    }

    public void dumpStatus(String msg) {
        System.out.println("(" + this + ") " + msg);
    }

    public void setInputMethodContext(InputMethodContext context) {
        initStatusWindow(context);

        imc = context;
        imc.enableClientWindowNotification(this, attachedStatusWindow);
    }

    private static void initStatusWindow(InputMethodContext context) {
        if (statusWindow == null) {
            String title;
            try {
                ResourceBundle rb = ResourceBundle
                        .getBundle("com.ibm.icu.dev.tool.ime.translit.Transliterator");
                title = rb.getString("title");
            } catch (MissingResourceException m) {
                System.out.println("Transliterator resources missing: " + m);
                title = "Transliterator Input Method";
            }

            Window sw = context.createInputMethodWindow(title, false);

            // get all the ICU Transliterators
            Enumeration en = Transliterator.getAvailableIDs();
            TreeSet types = new TreeSet(new LabelComparator());

            while (en.hasMoreElements()) {
                String id = (String) en.nextElement();
                String name = Transliterator.getDisplayName(id);
                JLabel label = new JLabel(name);
                label.setName(id);
                types.add(label);
            }

            // add the transliterators to the combo box

            choices = new JComboBox(types.toArray());

            choices.setEditable(false);
            choices.setSelectedIndex(0);
            choices.setRenderer(new NameRenderer());
            choices.setActionCommand("transliterator");

            choices.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (statusWindowOwner != null) {
                        statusWindowOwner.statusWindowAction(e);
                    }
                }
            });

            sw.add(choices);
            sw.pack();

            Dimension sd = Toolkit.getDefaultToolkit().getScreenSize();
            Dimension wd = sw.getSize();
            if (attachedStatusWindow) {
                attachedLimits = new Rectangle(0, 0, sd.width - wd.width,
                        sd.height - wd.height);
            } else {
                sw.setLocation(sd.width - wd.width, sd.height - wd.height - 25);
            }

            synchronized (TransliteratorInputMethod.class) {
                if (statusWindow == null) {
                    statusWindow = sw;
                }
            }
        }
    }

    private void statusWindowAction(ActionEvent e) {
        if (TRACE_MESSAGES)
            dumpStatus(">>status window action");
        JComboBox cb = (JComboBox) e.getSource();
        int si = cb.getSelectedIndex();
        if (si != selectedIndex) { // otherwise, we don't need to change
            if (TRACE_MESSAGES)
                dumpStatus("status window action oldIndex: " + selectedIndex
                        + " newIndex: " + si);

            selectedIndex = si;

            JLabel item = (JLabel) cb.getSelectedItem();

            // construct the actual transliterator
            // commit any text that may be present first
            commitAll();

            transliterator = Transliterator.getInstance(item.getName());
            desiredContext = transliterator.getMaximumContextLength();

            reset();
        }
        if (TRACE_MESSAGES)
            dumpStatus("<<status window action");
    }

    // java has no pin to rectangle function?
    private static void pin(Point p, Rectangle r) {
        if (p.x < r.x) {
            p.x = r.x;
        } else if (p.x > r.x + r.width) {
            p.x = r.x + r.width;
        }
        if (p.y < r.y) {
            p.y = r.y;
        } else if (p.y > r.y + r.height) {
            p.y = r.y + r.height;
        }
    }

    public void notifyClientWindowChange(Rectangle location) {
        if (TRACE_MESSAGES)
            dumpStatus(">>notify client window change: " + location);
        synchronized (TransliteratorInputMethod.class) {
            if (statusWindowOwner == this) {
                if (location == null) {
                    statusWindow.setVisible(false);
                } else {
                    attachedLocation = new Point(location.x, location.y
                            + location.height);
                    pin(attachedLocation, attachedLimits);
                    statusWindow.setLocation(attachedLocation);
                    statusWindow.setVisible(true);
                }
            }
        }
        if (TRACE_MESSAGES)
            dumpStatus("<<notify client window change: " + location);
    }

    public void activate() {
        if (TRACE_MESSAGES)
            dumpStatus(">>activate");

        synchronized (TransliteratorInputMethod.class) {
            if (statusWindowOwner != this) {
                if (TRACE_MESSAGES)
                    dumpStatus("setStatusWindowOwner from: " + statusWindowOwner + " to: " + this);

                statusWindowOwner = this;
                // will be null before first change notification
                if (attachedStatusWindow && attachedLocation != null) {
                    statusWindow.setLocation(attachedLocation);
                }
                choices.setSelectedIndex(selectedIndex == -1 ? choices
                        .getSelectedIndex() : selectedIndex);
            }

            choices.setForeground(Color.BLACK);
            statusWindow.setVisible(true);
        }
        if (TRACE_MESSAGES)
            dumpStatus("<<activate");
    }
    
    public void deactivate(boolean isTemporary) {
        if (TRACE_MESSAGES)
            dumpStatus(">>deactivate" + (isTemporary ? " (temporary)" : ""));
        if (!isTemporary) {
            synchronized (TransliteratorInputMethod.class) {
                choices.setForeground(Color.LIGHT_GRAY);
            }
        }
        if (TRACE_MESSAGES)
            dumpStatus("<<deactivate" + (isTemporary ? " (temporary)" : ""));
    }
    
    public void hideWindows() {
        if (TRACE_MESSAGES)
            dumpStatus(">>hideWindows");
        synchronized (TransliteratorInputMethod.class) {
            if (statusWindowOwner == this) {
                if (TRACE_MESSAGES)
                    dumpStatus("hiding");
                statusWindow.setVisible(false);
            }
        }
        if (TRACE_MESSAGES)
            dumpStatus("<<hideWindows");
    }
    
    public boolean setLocale(Locale locale) {
        return false;
    }
    
    public Locale getLocale() {
        return Locale.getDefault();
    }
    
    public void setCharacterSubsets(Character.Subset[] subsets) {
    }

    public void reconvert() {
        throw new UnsupportedOperationException();
    }

    public void removeNotify() {
        if (TRACE_MESSAGES)
            dumpStatus("**removeNotify");
    }

    public void endComposition() {
        commitAll();
    }

    public void dispose() {
        if (TRACE_MESSAGES)
            dumpStatus("**dispose");
    }
    
    public Object getControlObject() {
        return null;
    }
    
    public void setCompositionEnabled(boolean enable) {
        enabled = enable;
    }

    public boolean isCompositionEnabled() {
        return enabled;
    }

    // debugging
    private String eventInfo(AWTEvent event) {
        String info = event.toString();
        StringBuffer buf = new StringBuffer();
        int index1 = info.indexOf("[");
        int index2 = info.indexOf(",", index1);
        buf.append(info.substring(index1 + 1, index2));

        index1 = info.indexOf("] on ");
        index2 = info.indexOf("[", index1);
        if (index2 != -1) {
            int index3 = info.lastIndexOf(".", index2);
            if (index3 < index1 + 4) {
                index3 = index1 + 4;
            }
            buf.append(" on ");
            buf.append(info.substring(index3 + 1, index2));
        }
        return buf.toString();
    }

    public void dispatchEvent(AWTEvent event) {
        final int MODIFIERS = 
            InputEvent.CTRL_MASK | 
            InputEvent.META_MASK | 
            InputEvent.ALT_MASK | 
            InputEvent.ALT_GRAPH_MASK;
    
        switch (event.getID()) {
        case MouseEvent.MOUSE_PRESSED:
            if (enabled) {
                if (TRACE_EVENT) System.out.println("TIM: " + eventInfo(event));
                // we'll get this even if the user is scrolling, can we rely on the component?
                // commitAll(); // don't allow even clicks within our own edit area
            }
            break;
    
        case KeyEvent.KEY_TYPED: {
            if (enabled) {
                KeyEvent ke = (KeyEvent)event;
                if (TRACE_EVENT) System.out.println("TIM: " + eventInfo(ke));
                if ((ke.getModifiers() & MODIFIERS) != 0) {
                    commitAll(); // assume a command, let it go through
                } else {
                    if (handleTyped(ke.getKeyChar())) {
                        ke.consume();
                    }
                }
            }
        } break;
    
        case KeyEvent.KEY_PRESSED: {
            if (enabled) {
            KeyEvent ke = (KeyEvent)event;
            if (TRACE_EVENT) System.out.println("TIM: " + eventInfo(ke));
                if (handlePressed(ke.getKeyCode())) {
                    ke.consume();
                }
            }
        } break;
    
        case KeyEvent.KEY_RELEASED: {
            // this won't autorepeat, which is better for toggle actions
            KeyEvent ke = (KeyEvent)event;
            if (ke.getKeyCode() == KeyEvent.VK_SPACE && ke.isControlDown()) {
                setCompositionEnabled(!enabled);
            }
        } break;
    
        default:
            break;
        }
    }

    /** Wipe clean */
    private void reset() {
        buffer.delete(0, buffer.length());
        index.contextStart = index.contextLimit = index.start = index.limit = 0;
    }

    // committed}context-composed|composed
    //          ^       ^        ^
    //         cc     start    ctxLim

    private void traceBuffer(String msg, int cc, int off) {
        if (TRACE_BUFFER)
            System.out.println(Utility.escape(msg + ": '"
                    + buffer.substring(0, cc) + '}'
                    + buffer.substring(cc, index.start) + '-'
                    + buffer.substring(index.start, index.contextLimit) + '|'
                    + buffer.substring(index.contextLimit) + '\''));
    }

    private void update(boolean flush) {
        int len = buffer.length();
        String text = buffer.toString();
        AttributedString as = new AttributedString(text);

        int cc, off;
        if (flush) {
            off = index.contextLimit - len; // will be negative
            cc = index.start = index.limit = index.contextLimit = len;
        } else {
            cc = index.start > desiredContext ? index.start - desiredContext
                    : 0;
            off = index.contextLimit - cc;
        }

        if (index.start < len) {
            as.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
                    InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT,
                    index.start, len);
        }

        imc.dispatchInputMethodEvent(
                InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, as.getIterator(),
                cc, TextHitInfo.leading(off), null);

        traceBuffer("update", cc, off);

        if (cc > 0) {
            buffer.delete(0, cc);
            index.start -= cc;
            index.limit -= cc;
            index.contextLimit -= cc;
        }
    }

    private void updateCaret() {
        imc.dispatchInputMethodEvent(InputMethodEvent.CARET_POSITION_CHANGED,
                null, 0, TextHitInfo.leading(index.contextLimit), null);
        traceBuffer("updateCaret", 0, index.contextLimit);
    }
    
    private void caretToStart() {
        if (index.contextLimit > index.start) {
            index.contextLimit = index.limit = index.start;
            updateCaret();
        }
    }

    private void caretToLimit() {
        if (index.contextLimit < buffer.length()) {
            index.contextLimit = index.limit = buffer.length();
            updateCaret();
        }
    }

    private boolean caretTowardsStart() {
        int bufpos = index.contextLimit;
        if (bufpos > index.start) {
            --bufpos;
            if (bufpos > index.start
                    && UCharacter.isLowSurrogate(buffer.charAt(bufpos))
                    && UCharacter.isHighSurrogate(buffer.charAt(bufpos - 1))) {
                --bufpos;
            }
            index.contextLimit = index.limit = bufpos;
            updateCaret();
            return true;
        }
        return commitAll();
    }

    private boolean caretTowardsLimit() {
        int bufpos = index.contextLimit;
        if (bufpos < buffer.length()) {
            ++bufpos;
            if (bufpos < buffer.length()
                    && UCharacter.isLowSurrogate(buffer.charAt(bufpos))
                    && UCharacter.isHighSurrogate(buffer.charAt(bufpos - 1))) {
                ++bufpos;
            }
            index.contextLimit = index.limit = bufpos;
            updateCaret();
            return true;
        }
        return commitAll();
    }

    private boolean canBackspace() {
        return index.contextLimit > 0;
    }

    private boolean backspace() {
        int bufpos = index.contextLimit;
        if (bufpos > 0) {
            int limit = bufpos;
            --bufpos;
            if (bufpos > 0 && UCharacter.isLowSurrogate(buffer.charAt(bufpos))
                    && UCharacter.isHighSurrogate(buffer.charAt(bufpos - 1))) {
                --bufpos;
            }
            if (bufpos < index.start) {
                index.start = bufpos;
            }
            index.contextLimit = index.limit = bufpos;
            doDelete(bufpos, limit);
            return true;
        }
        return false;
    }

    private boolean canDelete() {
        return index.contextLimit < buffer.length();
    }

    private boolean delete() {
        int bufpos = index.contextLimit;
        if (bufpos < buffer.length()) {
            int limit = bufpos + 1;
            if (limit < buffer.length()
                    && UCharacter.isHighSurrogate(buffer.charAt(limit - 1))
                    && UCharacter.isLowSurrogate(buffer.charAt(limit))) {
                ++limit;
            }
            doDelete(bufpos, limit);
            return true;
        }
        return false;
    }

    private void doDelete(int start, int limit) {
        buffer.delete(start, limit);
        update(false);
    }

    private boolean commitAll() {
        if (buffer.length() > 0) {
            boolean atStart = index.start == index.contextLimit;
            boolean didConvert = buffer.length() > index.start;
            index.contextLimit = index.limit = buffer.length();
            transliterator.finishTransliteration(replaceableText, index);
            if (atStart) {
                index.start = index.limit = index.contextLimit = 0;
            }
            update(true);
            return didConvert;
        }
        return false;
    }

    private void clearAll() {
        int len = buffer.length();
        if (len > 0) {
            if (len > index.start) {
                buffer.delete(index.start, len);
            }
            update(true);
        }
    }

    private boolean insert(char c) {
        transliterator.transliterate(replaceableText, index, c);
        update(false);
        return true;
    }

    private boolean editing() {
        return buffer.length() > 0;
    }

    /**
     * The big problem is that from release to release swing changes how it
     * handles some characters like tab and backspace.  Sometimes it handles
     * them as keyTyped events, and sometimes it handles them as keyPressed
     * events.  If you want to allow the event to go through so swing handles
     * it, you have to allow one or the other to go through.  If you don't want
     * the event to go through so you can handle it, you have to stop the
     * event both places.
     * @return whether the character was handled
     */
    private boolean handleTyped(char ch) {
        if (enabled) {
            switch (ch) {
            case '\b': if (editing()) return backspace(); break;
            case '\t': if (editing()) { return commitAll(); } break;
            case '\u001b': if (editing()) { clearAll(); return true; } break;
            case '\u007f': if (editing()) return delete(); break;
            default: return insert(ch);
            }
        }
        return false;
    }

    /**
     * Handle keyPressed events.
     */
    private boolean handlePressed(int code) {
        if (enabled && editing()) {
            switch (code) {
            case KeyEvent.VK_PAGE_UP:
            case KeyEvent.VK_UP:
            case KeyEvent.VK_KP_UP:
            case KeyEvent.VK_HOME:
            caretToStart(); return true;
            case KeyEvent.VK_PAGE_DOWN:
            case KeyEvent.VK_DOWN:
            case KeyEvent.VK_KP_DOWN:
            case KeyEvent.VK_END:
            caretToLimit(); return true;
            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_KP_LEFT:
            return caretTowardsStart();
            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_KP_RIGHT:
            return caretTowardsLimit();
            case KeyEvent.VK_BACK_SPACE: 
            return canBackspace(); // unfortunately, in 1.5 swing handles this in keyPressed instead of keyTyped
            case KeyEvent.VK_DELETE: 
            return canDelete(); // this too?
            case KeyEvent.VK_TAB:
            case KeyEvent.VK_ENTER:
            return commitAll(); // so we'll never handle VK_TAB in keyTyped
            
            case KeyEvent.VK_SHIFT:
            case KeyEvent.VK_CONTROL:
            case KeyEvent.VK_ALT:
            return false; // ignore these unless a key typed event gets generated
            default: 
            // by default, let editor handle it, and we'll assume that it will tell us
            // to endComposition if it does anything funky with, e.g., function keys.
            return false;
            }
        }
        return false;
    }

    public String toString() {
        final String[] names = { 
            "alice", "bill", "carrie", "doug", "elena", "frank", "gertie", "howie", "ingrid", "john" 
        };
    
        if (id < names.length) {
            return names[id];
        } else {
            return names[id] + "-" + (id/names.length);
        }
    }
}

class NameRenderer extends JLabel implements ListCellRenderer {

    /**
     * For serialization
     */
    private static final long serialVersionUID = -210152863798631747L;

    public Component getListCellRendererComponent(
        JList list,
        Object value,
        int index,
        boolean isSelected,
        boolean cellHasFocus) {

        String s = ((JLabel)value).getText();
        setText(s);

        if (isSelected) {
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }

        setEnabled(list.isEnabled());
        setFont(list.getFont());
        setOpaque(true);
        return this;
    }
}

class LabelComparator implements Comparator {
    public int compare(Object obj1, Object obj2) {
        Collator collator = Collator.getInstance();
        return collator.compare(((JLabel)obj1).getText(), ((JLabel)obj2).getText());
    }

    public boolean equals(Object obj1) {
        return this.equals(obj1);
    }
}


