/*
 *******************************************************************************
 * Copyright (C) 2004, 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 e = Transliterator.getAvailableIDs();
	    TreeSet types = new TreeSet(new LabelComparator());

	    while(e.hasMoreElements()) {
		String id = (String) e.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;
		if (attachedStatusWindow && attachedLocation != null) { // will be null before first change notification
		    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 {

    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);
    }
}


