/*
 * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 */

package com.sun.inputmethods.internal.codepointim;
import java.text.AttributedCharacterIterator;
import java.util.Map;

import java.awt.AWTEvent;
import java.awt.Toolkit;
import java.awt.Rectangle;
import java.awt.event.InputMethodEvent;
import java.awt.event.KeyEvent;
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.io.IOException;
import java.text.AttributedString;
import java.util.Locale;

/**
 * The Code Point Input Method is a simple input method that allows Unicode
 * characters to be entered using their code point or code unit values. See the
 * accompanying file README.txt for more information.
 *
 * @author Brian Beck
 */
public class CodePointInputMethod implements InputMethod {

    private static final int UNSET           = 0;
    private static final int ESCAPE          = 1; // \u0000       - \uFFFF
    private static final int SPECIAL_ESCAPE  = 2; // \U000000     - \U10FFFF
    private static final int SURROGATE_PAIR  = 3; // \uD800\uDC00 - \uDBFF\uDFFF

    private InputMethodContext context;
    private Locale locale;
    private StringBuffer buffer;
    private int insertionPoint;
    private int format = UNSET;


    public CodePointInputMethod() throws IOException {
    }

    /**
     * This is the input method's main routine.  The composed text is stored
     * in buffer.
     */
    public void dispatchEvent(AWTEvent event) {
        // This input method handles KeyEvent only.
        if (!(event instanceof KeyEvent)) {
            return;
        }

        KeyEvent e = (KeyEvent) event;
        int eventID = event.getID();
        boolean notInCompositionMode = buffer.length() == 0;

        if (eventID == KeyEvent.KEY_PRESSED) {
            // If we are not in composition mode, pass through
            if (notInCompositionMode)  {
                return;
            }

            switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT:
                    moveCaretLeft();
                    break;
                case KeyEvent.VK_RIGHT:
                    moveCaretRight();
                    break;
            }
        } else if (eventID == KeyEvent.KEY_TYPED) {
            char c = e.getKeyChar();

            // If we are not in composition mode, wait a back slash
            if (notInCompositionMode)  {
                // If the type character is not a back slash, pass through
                if (c != '\\') {
                    return;
                }

                startComposition();     // Enter to composition mode
            } else {
                switch (c) {
                case ' ':       // Exit from composition mode
                    finishComposition();
                    break;
                case '\u007f':  // Delete
                    deleteCharacter();
                    break;
                case '\b':      // BackSpace
                    deletePreviousCharacter();
                    break;
                case '\u001b':  // Escape
                    cancelComposition();
                    break;
                case '\n':      // Return
                case '\t':      // Tab
                    sendCommittedText();
                    break;
                default:
                    composeUnicodeEscape(c);
                    break;
                }
            }
        } else {  // KeyEvent.KEY_RELEASED
            // If we are not in composition mode, pass through
            if (notInCompositionMode)  {
                return;
            }
        }

        e.consume();
    }

    private void composeUnicodeEscape(char c) {
        switch (buffer.length()) {
            case  1:  // \\
                waitEscapeCharacter(c);
                break;
            case 2:  // \\u or \\U
            case 3:  // \\ux or \\Ux
            case 4:  // \\uxx or \\Uxx
                waitDigit(c);
                break;
            case 5:  // \\uxxx or \\Uxxx
                if (format == SPECIAL_ESCAPE) {
                    waitDigit(c);
                } else {
                    waitDigit2(c);
                }
                break;
            case 6:  // \\uxxxx or \\Uxxxx
                if (format == SPECIAL_ESCAPE) {
                    waitDigit(c);
                } else if (format == SURROGATE_PAIR) {
                    waitBackSlashOrLowSurrogate(c);
                } else {
                    beep();
                }
                break;
            case 7:  // \\Uxxxxx
                // Only SPECIAL_ESCAPE format uses this state.
                // Since the second "\\u" of SURROGATE_PAIR format is inserted
                // automatically, users don't have to type these keys.
                waitDigit(c);
                break;
            case 8:  // \\uxxxx\\u
            case 9:  // \\uxxxx\\ux
            case 10: // \\uxxxx\\uxx
            case 11: // \\uxxxx\\uxxx
                if (format == SURROGATE_PAIR) {
                    waitDigit(c);
                } else {
                    beep();
                }
                break;
            default:
                beep();
                break;
        }
    }

    private void waitEscapeCharacter(char c) {
        if (c == 'u' || c == 'U') {
            buffer.append(c);
            insertionPoint++;
            sendComposedText();
            format = (c == 'u') ? ESCAPE : SPECIAL_ESCAPE;
        } else {
            if (c != '\\') {
                buffer.append(c);
                insertionPoint++;
            }
            sendCommittedText();
        }
    }

    private void waitDigit(char c) {
        if (Character.digit(c, 16) != -1) {
            buffer.insert(insertionPoint++, c);
            sendComposedText();
        } else {
            beep();
        }
    }

    private void waitDigit2(char c) {
        if (Character.digit(c, 16) != -1) {
            buffer.insert(insertionPoint++, c);
            char codePoint = (char)getCodePoint(buffer, 2, 5);
            if (Character.isHighSurrogate(codePoint)) {
                format = SURROGATE_PAIR;
                buffer.append("\\u");
                insertionPoint = 8;
            } else {
                format = ESCAPE;
            }
            sendComposedText();
        } else {
            beep();
        }
    }

    private void waitBackSlashOrLowSurrogate(char c) {
        if (insertionPoint == 6) {
            if (c == '\\') {
                buffer.append(c);
                buffer.append('u');
                insertionPoint = 8;
                sendComposedText();
            } else if (Character.digit(c, 16) != -1) {
                buffer.append("\\u");
                buffer.append(c);
                insertionPoint = 9;
                sendComposedText();
            } else {
                beep();
            }
        } else {
            beep();
        }
    }

    /**
     * Send the composed text to the client.
     */
    private void sendComposedText() {
        AttributedString as = new AttributedString(buffer.toString());
        as.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
                        InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT);
        context.dispatchInputMethodEvent(
                                  InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                  as.getIterator(), 0,
                                  TextHitInfo.leading(insertionPoint), null);
    }

    /**
     * Send the committed text to the client.
     */
    private void sendCommittedText() {
        AttributedString as = new AttributedString(buffer.toString());
        context.dispatchInputMethodEvent(
                                  InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                  as.getIterator(), buffer.length(),
                                  TextHitInfo.leading(insertionPoint), null);

        buffer.setLength(0);
        insertionPoint = 0;
        format = UNSET;
    }

    /**
     * Move the insertion point one position to the left in the composed text.
     * Do not let the caret move to the left of the "\\u" or "\\U".
     */
    private void moveCaretLeft() {
        int len = buffer.length();
        if (--insertionPoint < 2) {
            insertionPoint++;
            beep();
        } else if (format == SURROGATE_PAIR && insertionPoint == 7) {
            insertionPoint = 8;
            beep();
        }

        context.dispatchInputMethodEvent(
                                  InputMethodEvent.CARET_POSITION_CHANGED,
                                  null, 0,
                                  TextHitInfo.leading(insertionPoint), null);
    }

    /**
     * Move the insertion point one position to the right in the composed text.
     */
    private void moveCaretRight() {
        int len = buffer.length();
        if (++insertionPoint > len) {
            insertionPoint = len;
            beep();
        }

        context.dispatchInputMethodEvent(
                                  InputMethodEvent.CARET_POSITION_CHANGED,
                                  null, 0,
                                  TextHitInfo.leading(insertionPoint), null);
    }

    /**
     * Delete the character preceding the insertion point in the composed text.
     * If the insertion point is not at the end of the composed text and the
     * preceding text is "\\u" or "\\U", ring the bell.
     */
    private void deletePreviousCharacter() {
        if (insertionPoint == 2) {
            if (buffer.length() == 2) {
                cancelComposition();
            } else {
                // Do not allow deletion of the leading "\\u" or "\\U" if there
                // are other digits in the composed text.
                beep();
            }
        } else if (insertionPoint == 8) {
            if (buffer.length() == 8) {
                if (format == SURROGATE_PAIR) {
                    buffer.deleteCharAt(--insertionPoint);
                }
                buffer.deleteCharAt(--insertionPoint);
                sendComposedText();
            } else {
                // Do not allow deletion of the second "\\u" if there are other
                // digits in the composed text.
                beep();
            }
        } else {
            buffer.deleteCharAt(--insertionPoint);
            if (buffer.length() == 0) {
                sendCommittedText();
            } else {
                sendComposedText();
            }
        }
    }

    /**
     * Delete the character following the insertion point in the composed text.
     * If the insertion point is at the end of the composed text, ring the bell.
     */
    private void deleteCharacter() {
        if (insertionPoint < buffer.length()) {
            buffer.deleteCharAt(insertionPoint);
            sendComposedText();
        } else {
            beep();
        }
    }

    private void startComposition() {
        buffer.append('\\');
        insertionPoint = 1;
        sendComposedText();
    }

    private void cancelComposition() {
        buffer.setLength(0);
        insertionPoint = 0;
        sendCommittedText();
    }

    private void finishComposition() {
        int len = buffer.length();
        if (len == 6 && format != SPECIAL_ESCAPE) {
            char codePoint = (char)getCodePoint(buffer, 2, 5);
            if (Character.isValidCodePoint(codePoint) && codePoint != 0xFFFF) {
                buffer.setLength(0);
                buffer.append(codePoint);
                sendCommittedText();
                return;
            }
        } else if (len == 8 && format == SPECIAL_ESCAPE) {
            int codePoint = getCodePoint(buffer, 2, 7);
            if (Character.isValidCodePoint(codePoint) && codePoint != 0xFFFF) {
                buffer.setLength(0);
                buffer.appendCodePoint(codePoint);
                sendCommittedText();
                return;
            }
        } else if (len == 12 && format == SURROGATE_PAIR) {
            char[] codePoint = {
                (char)getCodePoint(buffer, 2, 5),
                (char)getCodePoint(buffer, 8, 11)
            };
            if (Character.isHighSurrogate(codePoint[0]) &&
                Character.isLowSurrogate(codePoint[1])) {
                buffer.setLength(0);
                buffer.append(codePoint);
                sendCommittedText();
                return;
            }
        }

        beep();
    }

    private int getCodePoint(StringBuffer sb, int from, int to) {
        int value = 0;
        for (int i = from; i <= to; i++) {
            value = (value<<4) + Character.digit(sb.charAt(i), 16);
        }
        return value;
    }

    private static void beep() {
        Toolkit.getDefaultToolkit().beep();
    }


    public void activate() {
        if (buffer == null) {
            buffer = new StringBuffer(12);
            insertionPoint = 0;
        }
    }

    public void deactivate(boolean isTemporary) {
        if (!isTemporary) {
            buffer = null;
        }
    }

    public void dispose() {
    }

    public Object getControlObject() {
        return null;
    }

    public void endComposition() {
        sendCommittedText();
    }

    public Locale getLocale() {
        return locale;
    }

    public void hideWindows() {
    }

    public boolean isCompositionEnabled() {
        // always enabled
        return true;
    }

    public void notifyClientWindowChange(Rectangle location) {
    }

    public void reconvert() {
        // not supported yet
        throw new UnsupportedOperationException();
    }

    public void removeNotify() {
    }

    public void setCharacterSubsets(Character.Subset[] subsets) {
    }

    public void setCompositionEnabled(boolean enable) {
        // not supported yet
        throw new UnsupportedOperationException();
    }

    public void setInputMethodContext(InputMethodContext context) {
        this.context = context;
    }

    /*
     * The Code Point Input Method supports all locales.
     */
    public boolean setLocale(Locale locale) {
        this.locale = locale;
        return true;
    }
}
