/*
 * Copyright (C) 2008,2009  OMRON SOFTWARE Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jp.co.omronsoft.openwnn;

import jp.co.omronsoft.openwnn.EN.*;
import android.content.SharedPreferences;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Message;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.MetaKeyKeyListener;
import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;

/**
 * The OpenWnn English IME class.
 *
 * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD.  All Rights Reserved.
 */
public class OpenWnnEN extends OpenWnn {
    /** A space character */
    private static final char[] SPACE = {' '};

    /** Character style of underline */
    private static final CharacterStyle SPAN_UNDERLINE   = new UnderlineSpan();
    /** Highlight color style for the selected string  */
    private static final CharacterStyle SPAN_EXACT_BGCOLOR_HL     = new BackgroundColorSpan(0xFF66CDAA);
    /** Highlight color style for the composing text */
    private static final CharacterStyle SPAN_REMAIN_BGCOLOR_HL    = new BackgroundColorSpan(0xFFF0FFFF);
    /** Highlight text color */
    private static final CharacterStyle SPAN_TEXTCOLOR  = new ForegroundColorSpan(0xFF000000);

    /** A private area code(ALT+SHIFT+X) to be ignore (G1 specific). */
    private static final int PRIVATE_AREA_CODE = 61184;
    /** Never move cursor in to the composing text (adapting to IMF's specification change) */
    private static final boolean FIX_CURSOR_TEXT_END = true;

    /** Spannable string for the composing text */
    protected SpannableStringBuilder mDisplayText;

    /** Characters treated as a separator */
    private String mWordSeparators;
    /** Previous event's code */
    private int mPreviousEventCode;

    /** Array of words from the user dictionary */
    private WnnWord[] mUserDictionaryWords = null;

    /** The converter for English prediction/spell correction */
    private OpenWnnEngineEN mConverterEN;
    /** The symbol list generator */
    private SymbolList mSymbolList;
    /** Whether it is displaying symbol list */
    private boolean mSymbolMode;
    /** Whether prediction is enabled */
    private boolean mOptPrediction;
    /** Whether spell correction is enabled */
    private boolean mOptSpellCorrection;
    /** Whether learning is enabled */
    private boolean mOptLearning;

    /** SHIFT key state */
    private int mHardShift;
    /** SHIFT key state (pressing) */
    private boolean mShiftPressing;
    /** ALT key state */
    private int mHardAlt;
    /** ALT key state (pressing) */
    private boolean mAltPressing;

    /** Instance of this service */
    private static OpenWnnEN mSelf = null;

    /** Shift lock toggle definition */
    private static final int[] mShiftKeyToggle = {0, MetaKeyKeyListener.META_SHIFT_ON, MetaKeyKeyListener.META_CAP_LOCKED};
    /** ALT lock toggle definition */
    private static final int[] mAltKeyToggle = {0, MetaKeyKeyListener.META_ALT_ON, MetaKeyKeyListener.META_ALT_LOCKED};
    /** Auto caps mode */
    private boolean mAutoCaps = false;

    /** Whether dismissing the keyboard when the enter key is pressed */
    private boolean mEnableAutoHideKeyboard = true;

    /** Tutorial */
    private TutorialEN mTutorial;

    /** Whether tutorial mode or not */
    private boolean mEnableTutorial;

    /** Message for {@code mHandler} (execute prediction) */
    private static final int MSG_PREDICTION = 0;

    /** Message for {@code mHandler} (execute tutorial) */
    private static final int MSG_START_TUTORIAL = 1;

    /** Message for {@code mHandler} (close) */
    private static final int MSG_CLOSE = 2;

    /** Delay time(msec.) to start prediction after key input when the candidates view is not shown. */
    private static final int PREDICTION_DELAY_MS_1ST = 200;

    /** Delay time(msec.) to start prediction after key input when the candidates view is shown. */
    private static final int PREDICTION_DELAY_MS_SHOWING_CANDIDATE = 200;

    /** {@code Handler} for drawing candidates/displaying tutorial */
    Handler mHandler = new Handler() {
            @Override public void handleMessage(Message msg) {
                switch (msg.what) {
                case MSG_PREDICTION:
                    updatePrediction();
                    break;
                case MSG_START_TUTORIAL:
                    if (mTutorial == null) {
                        if (isInputViewShown()) {
                            DefaultSoftKeyboardEN inputManager = ((DefaultSoftKeyboardEN) mInputViewManager);
                            View v = inputManager.getKeyboardView();
                            mTutorial = new TutorialEN(OpenWnnEN.this, v, inputManager);

                            mTutorial.start();
                        } else {
                            /* Try again soon if the view is not yet showing */
                            sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), 100);
                        }
                    }
                    break;
                case MSG_CLOSE:
                    if (mConverterEN != null) mConverterEN.close();
                    if (mSymbolList != null) mSymbolList.close();
                    break;
                }
            }
        };

    /**
     * Constructor
     */
    public OpenWnnEN() {
        super();
        mSelf = this;

        /* used by OpenWnn */
        mComposingText = new ComposingText();
        mCandidatesViewManager = new TextCandidatesViewManager(-1);
        mInputViewManager = new DefaultSoftKeyboardEN();
        mConverterEN = new OpenWnnEngineEN("/data/data/jp.co.omronsoft.openwnn/writableEN.dic");
        mConverter = mConverterEN;
        mSymbolList = null;

        /* etc */
        mDisplayText = new SpannableStringBuilder();
        mAutoHideMode = false;
        mSymbolMode = false;
        mOptPrediction = true;
        mOptSpellCorrection = true;
        mOptLearning = true;
    }

    /**
     * Constructor
     *
     * @param context       The context
     */
    public OpenWnnEN(Context context) {
        this();
        attachBaseContext(context);
    }
    /**
     * Get the instance of this service.
     * <br>
     * Before using this method, the constructor of this service must be invoked.
     *
     * @return      The instance of this object
     */
    public static OpenWnnEN getInstance() {
        return mSelf;
    }

    /**
     * Insert a character into the composing text.
     *
     * @param chars     A array of character
     */
    private void insertCharToComposingText(char[] chars) {
        StrSegment seg = new StrSegment(chars);

        if (chars[0] == SPACE[0] || chars[0] == '\u0009') {
            /* if the character is a space, commit the composing text */
            commitText(1);
            commitText(seg.string);
            mComposingText.clear();
        } else if (mWordSeparators.contains(seg.string)) {
            /* if the character is a separator, remove an auto-inserted space and commit the composing text. */
            if (mPreviousEventCode == OpenWnnEvent.SELECT_CANDIDATE) {
                mInputConnection.deleteSurroundingText(1, 0);
            }
            commitText(1);
            commitText(seg.string);
            mComposingText.clear();
        } else {
            mComposingText.insertStrSegment(0, 1, seg);
            updateComposingText(1);
        }
    }

    /**
     * Insert a character into the composing text.
     *
     * @param charCode      A character code
     * @return              {@code true} if success; {@code false} if an error occurs.
     */
    private boolean insertCharToComposingText(int charCode) {
        if (charCode == 0) {
            return false;
        }
        insertCharToComposingText(Character.toChars(charCode));
        return true;
    }

    /**
     * Get the shift key state from the editor.
     *
     * @param editor    Editor
     *
     * @return          State ID of the shift key (0:off, 1:on)
     */
    protected int getShiftKeyState(EditorInfo editor) {
        return (getCurrentInputConnection().getCursorCapsMode(editor.inputType) == 0) ? 0 : 1;
    }

    /**
     * Set the mode of the symbol list.
     *
     * @param mode      {@code SymbolList.SYMBOL_ENGLISH} or {@code null}.
     */
    private void setSymbolMode(String mode) {
        if (mode != null) {
            mHandler.removeMessages(MSG_PREDICTION);
            mSymbolMode = true;
            mSymbolList.setDictionary(mode);
            mConverter = mSymbolList;
        } else {
            if (!mSymbolMode) {
                return;
            }
            mHandler.removeMessages(MSG_PREDICTION);
            mSymbolMode = false;
            mConverter = mConverterEN;
        }
    }

    /***********************************************************************
     * InputMethodServer
     ***********************************************************************/
    /** @see jp.co.omronsoft.openwnn.OpenWnn#onCreate */
    @Override public void onCreate() {
        super.onCreate();
        mWordSeparators = getResources().getString(R.string.en_word_separators);

        if (mSymbolList == null) {
            mSymbolList = new SymbolList(this, SymbolList.LANG_EN);
        }
    }

    /** @see jp.co.omronsoft.openwnn.OpenWnn#onCreateInputView */
    @Override public View onCreateInputView() {
        int hiddenState = getResources().getConfiguration().hardKeyboardHidden;
        boolean hidden = (hiddenState == Configuration.HARDKEYBOARDHIDDEN_YES);
        ((DefaultSoftKeyboardEN) mInputViewManager).setHardKeyboardHidden(hidden);
        mEnableTutorial = hidden;

        return super.onCreateInputView();
    }

    /** @see jp.co.omronsoft.openwnn.OpenWnn#onStartInputView */
    @Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
        super.onStartInputView(attribute, restarting);

        /* initialize views */
        mCandidatesViewManager.clearCandidates();
        mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_CLOSE);

        mHardShift = 0;
        mHardAlt   = 0;
        updateMetaKeyStateDisplay();

        /* load preferences */
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);

        /* auto caps mode */
        mAutoCaps = pref.getBoolean("auto_caps", true);

        /* set TextCandidatesViewManager's option */
        ((TextCandidatesViewManager)mCandidatesViewManager).setAutoHide(true);

        /* display status icon */
        showStatusIcon(R.drawable.immodeic_half_alphabet);

        if (mComposingText != null) {
            mComposingText.clear();
        }
        /* initialize the engine's state */
        fitInputType(pref, attribute);

        ((DefaultSoftKeyboard) mInputViewManager).resetCurrentKeyboard();
    }

    /** @see jp.co.omronsoft.openwnn.OpenWnn#hideWindow */
    @Override public void hideWindow() {
        mComposingText.clear();
        mInputViewManager.onUpdateState(this);
        mHandler.removeMessages(MSG_START_TUTORIAL);
        mInputViewManager.closing();
        if (mTutorial != null) {
            mTutorial.close();
            mTutorial = null;
        }

        super.hideWindow();
    }

    /** @see jp.co.omronsoft.openwnn.OpenWnn#onUpdateSelection */
    @Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
            int newSelStart, int newSelEnd, int candidatesStart,
            int candidatesEnd) {

        boolean isNotComposing = ((candidatesStart < 0) && (candidatesEnd < 0));
        if (isNotComposing) {
            mComposingText.clear();
            updateComposingText(1);
        } else {
            if (mComposingText.size(1) != 0) {
                updateComposingText(1);
            }
        }
    }

    /** @see jp.co.omronsoft.openwnn.OpenWnn#onConfigurationChanged */
    @Override public void onConfigurationChanged(Configuration newConfig) {
        try {
            super.onConfigurationChanged(newConfig);
            if (mInputConnection != null) {
                updateComposingText(1);
            }
            /* Hardware keyboard */
            int hiddenState = newConfig.hardKeyboardHidden;
            boolean hidden = (hiddenState == Configuration.HARDKEYBOARDHIDDEN_YES);
            mEnableTutorial = hidden;
        } catch (Exception ex) {
        }
    }

    /** @see jp.co.omronsoft.openwnn.OpenWnn#onEvaluateFullscreenMode */
    @Override public boolean onEvaluateFullscreenMode() {
        return false;
    }

    /** @see jp.co.omronsoft.openwnn.OpenWnn#onEvaluateInputViewShown */
    @Override public boolean onEvaluateInputViewShown() {
        return true;
    }

    /***********************************************************************
     * OpenWnn
     ***********************************************************************/
    /** @see jp.co.omronsoft.openwnn.OpenWnn#onEvent */
    @Override synchronized public boolean onEvent(OpenWnnEvent ev) {
        /* handling events which are valid when InputConnection is not active. */
        switch (ev.code) {

        case OpenWnnEvent.KEYUP:
            onKeyUpEvent(ev.keyEvent);
            return true;

        case OpenWnnEvent.INITIALIZE_LEARNING_DICTIONARY:
            return mConverterEN.initializeDictionary( WnnEngine.DICTIONARY_TYPE_LEARN );

        case OpenWnnEvent.INITIALIZE_USER_DICTIONARY:
            return mConverterEN.initializeDictionary( WnnEngine.DICTIONARY_TYPE_USER );

        case OpenWnnEvent.LIST_WORDS_IN_USER_DICTIONARY:
            mUserDictionaryWords = mConverterEN.getUserDictionaryWords( );
            return true;

        case OpenWnnEvent.GET_WORD:
            if( mUserDictionaryWords != null ) {
                ev.word = mUserDictionaryWords[ 0 ];
                for( int i = 0 ; i < mUserDictionaryWords.length-1 ; i++ ) {
                    mUserDictionaryWords[ i ] = mUserDictionaryWords[ i + 1 ];
                }
                mUserDictionaryWords[ mUserDictionaryWords.length-1 ] = null;
                if( mUserDictionaryWords[ 0 ] == null ) {
                    mUserDictionaryWords = null;
                }
                return true;
            }
            break;

        case OpenWnnEvent.ADD_WORD:
            mConverterEN.addWord(ev.word);
            return true;

        case OpenWnnEvent.DELETE_WORD:
            mConverterEN.deleteWord(ev.word);
            return true;

        case OpenWnnEvent.CHANGE_MODE:
            return false;

        case OpenWnnEvent.UPDATE_CANDIDATE:
            updateComposingText(ComposingText.LAYER1);
            return true;

        case OpenWnnEvent.CHANGE_INPUT_VIEW:
            setInputView(onCreateInputView());
            return true;

        case OpenWnnEvent.CANDIDATE_VIEW_TOUCH:
            boolean ret;
                ret = ((TextCandidatesViewManager)mCandidatesViewManager).onTouchSync();
            return ret;

        default:
            break;
        }

        dismissPopupKeyboard();
        KeyEvent keyEvent = ev.keyEvent;
        int keyCode = 0;
        if (keyEvent != null) {
            keyCode = keyEvent.getKeyCode();
        }
        if (mDirectInputMode) {
            if (ev.code == OpenWnnEvent.INPUT_SOFT_KEY && mInputConnection != null) {
                mInputConnection.sendKeyEvent(keyEvent);
                mInputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
                                                           keyEvent.getKeyCode()));
            }
            return false;
        }

        if (ev.code == OpenWnnEvent.LIST_CANDIDATES_FULL) {
            mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_FULL);
            return true;
        } else if (ev.code == OpenWnnEvent.LIST_CANDIDATES_NORMAL) {
            mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
            return true;
        }

        boolean ret = false;
        switch (ev.code) {
        case OpenWnnEvent.INPUT_CHAR:
             ((TextCandidatesViewManager)mCandidatesViewManager).setAutoHide(false);
            EditorInfo edit = getCurrentInputEditorInfo();
            if( edit.inputType == EditorInfo.TYPE_CLASS_PHONE){
                commitText(new String(ev.chars));
            }else{
                setSymbolMode(null);
                insertCharToComposingText(ev.chars);
                ret = true;
                mPreviousEventCode = ev.code;
            }
            break;

        case OpenWnnEvent.INPUT_KEY:
            keyCode = ev.keyEvent.getKeyCode();
            /* update shift/alt state */
            switch (keyCode) {
            case KeyEvent.KEYCODE_ALT_LEFT:
            case KeyEvent.KEYCODE_ALT_RIGHT:
                if (ev.keyEvent.getRepeatCount() == 0) {
                    if (++mHardAlt > 2) { mHardAlt = 0; }
                }
                mAltPressing   = true;
                updateMetaKeyStateDisplay();
                return true;

            case KeyEvent.KEYCODE_SHIFT_LEFT:
            case KeyEvent.KEYCODE_SHIFT_RIGHT:
                if (ev.keyEvent.getRepeatCount() == 0) {
                    if (++mHardShift > 2) { mHardShift = 0; }
                }
                mShiftPressing = true;
                updateMetaKeyStateDisplay();
                return true;
            }
            setSymbolMode(null);
            updateComposingText(1);
            /* handle other key event */
            ret = processKeyEvent(ev.keyEvent);
            mPreviousEventCode = ev.code;
            break;

        case OpenWnnEvent.INPUT_SOFT_KEY:
            setSymbolMode(null);
            updateComposingText(1);
            ret = processKeyEvent(ev.keyEvent);
            if (!ret) {
            	int code = keyEvent.getKeyCode();
            	if (code == KeyEvent.KEYCODE_ENTER) {
                    sendKeyChar('\n');
            	} else {
                    mInputConnection.sendKeyEvent(keyEvent);
                    mInputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, code));
            	}
                ret = true;
            }
            mPreviousEventCode = ev.code;
            break;

        case OpenWnnEvent.SELECT_CANDIDATE:
            if (mSymbolMode) {
                commitText(ev.word, false);
            } else {
                if (mWordSeparators.contains(ev.word.candidate) &&
                    mPreviousEventCode == OpenWnnEvent.SELECT_CANDIDATE) {
                    mInputConnection.deleteSurroundingText(1, 0);
                }
                commitText(ev.word, true);
            }
            mComposingText.clear();
            mPreviousEventCode = ev.code;
            updateComposingText(1);
            break;

        case OpenWnnEvent.LIST_SYMBOLS:
            commitText(1);
            mComposingText.clear();
            setSymbolMode(SymbolList.SYMBOL_ENGLISH);
            updateComposingText(1);
            break;

        default:
            break;
        }

        if (mCandidatesViewManager.getViewType() == CandidatesViewManager.VIEW_TYPE_FULL) {
        	mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
        }

        return ret;
    }

    /***********************************************************************
     * OpenWnnEN
     ***********************************************************************/
    /**
     * Handling KeyEvent
     * <br>
     * This method is called from {@link #onEvent()}.
     *
     * @param ev   A key event
     * @return      {@code true} if the event is processed in this method; {@code false} if the event is not processed in this method
     */
    private boolean processKeyEvent(KeyEvent ev) {

        int key = ev.getKeyCode();
        EditorInfo edit = getCurrentInputEditorInfo();
        /* keys which produce a glyph */
        if (ev.isPrintingKey()) {
            /* do nothing if the character is not able to display or the character is dead key */
            if ((mHardShift > 0 && mHardAlt > 0) || (ev.isAltPressed() && ev.isShiftPressed())) {
                int charCode = ev.getUnicodeChar(MetaKeyKeyListener.META_SHIFT_ON | MetaKeyKeyListener.META_ALT_ON);
                if (charCode == 0 || (charCode & KeyCharacterMap.COMBINING_ACCENT) != 0 || charCode == PRIVATE_AREA_CODE) {
                    if(mHardShift == 1){
                        mShiftPressing = false;
                    }
                    if(mHardAlt == 1){
                        mAltPressing   = false;
                    }
                    if(!ev.isAltPressed()){
                        if (mHardAlt == 1) {
                            mHardAlt = 0;
                        }
                    }
                    if(!ev.isShiftPressed()){
                        if (mHardShift == 1) {
                            mHardShift = 0;
                        }
                    }
                    if(!ev.isShiftPressed() && !ev.isAltPressed()){
                        updateMetaKeyStateDisplay();
                    }
                    return true;
                }
            }

            ((TextCandidatesViewManager)mCandidatesViewManager).setAutoHide(false);

            /* get the key character */
            if (mHardShift== 0  && mHardAlt == 0) {
                /* no meta key is locked */
                int shift = (mAutoCaps) ? getShiftKeyState(edit) : 0;
                if (shift != mHardShift && (key >= KeyEvent.KEYCODE_A && key <= KeyEvent.KEYCODE_Z)) {
                    /* handling auto caps for a alphabet character */
                    insertCharToComposingText(ev.getUnicodeChar(MetaKeyKeyListener.META_SHIFT_ON));
                } else {
                    insertCharToComposingText(ev.getUnicodeChar());
                }
            } else {
                insertCharToComposingText(ev.getUnicodeChar(mShiftKeyToggle[mHardShift]
                                                            | mAltKeyToggle[mHardAlt]));
                if(mHardShift == 1){
                    mShiftPressing = false;
                }
                if(mHardAlt == 1){
                    mAltPressing   = false;
                }
                /* back to 0 (off) if 1 (on/not locked) */
                if(!ev.isAltPressed()){
                    if (mHardAlt == 1) {
                        mHardAlt = 0;
                    }
                }
                if(!ev.isShiftPressed()){
                    if (mHardShift == 1) {
                        mHardShift = 0;
                    }
                }
                if(!ev.isShiftPressed() && !ev.isAltPressed()){
                    updateMetaKeyStateDisplay();
                }
            }

            if (edit.inputType == EditorInfo.TYPE_CLASS_PHONE) {
                commitText(1);
                mComposingText.clear();
                return true;
            }
            return true;

        } else if (key == KeyEvent.KEYCODE_SPACE) {
            if (ev.isAltPressed()) {
                /* display the symbol list (G1 specific. same as KEYCODE_SYM) */
                commitText(1);
                mComposingText.clear();
                setSymbolMode(SymbolList.SYMBOL_ENGLISH);
                updateComposingText(1);
                mHardAlt = 0;
                updateMetaKeyStateDisplay();
            } else {
                insertCharToComposingText(SPACE);
            }
            return true;
        } else if (key == KeyEvent.KEYCODE_SYM) {
            /* display the symbol list */
            commitText(1);
            mComposingText.clear();
            setSymbolMode(SymbolList.SYMBOL_ENGLISH);
            updateComposingText(1);
            mHardAlt = 0;
            updateMetaKeyStateDisplay();
        }


        /* Functional key */
        if (mComposingText.size(1) > 0) {
            switch (key) {
            case KeyEvent.KEYCODE_DEL:
                mComposingText.delete(1, false);
                updateComposingText(1);
                return true;

            case KeyEvent.KEYCODE_BACK:
                if (mCandidatesViewManager.getViewType() == CandidatesViewManager.VIEW_TYPE_FULL) {
                    mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
                } else {
                    mComposingText.clear();
                    updateComposingText(1);
                }
                return true;

            case KeyEvent.KEYCODE_DPAD_LEFT:
                mComposingText.moveCursor(1, -1);
                updateComposingText(1);
                return true;

            case KeyEvent.KEYCODE_DPAD_RIGHT:
                mComposingText.moveCursor(1, 1);
                updateComposingText(1);
                return true;

            case KeyEvent.KEYCODE_ENTER:
            case KeyEvent.KEYCODE_DPAD_CENTER:
                commitText(1);
                mComposingText.clear();
                if (mEnableAutoHideKeyboard) {
                    mInputViewManager.closing();
                    requestHideSelf(0);
                }
                return true;

            default:
                break;
            }
        } else {
            /* if there is no composing string. */
            if (mCandidatesViewManager.getCurrentView().isShown()) {
            	if (key == KeyEvent.KEYCODE_BACK) {
            		if (mCandidatesViewManager.getViewType() == CandidatesViewManager.VIEW_TYPE_FULL) {
            			mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
            		} else {
            			mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_CLOSE);
            		}
            		return true;
            	}
            } else {
                switch (key) {
                case KeyEvent.KEYCODE_DPAD_CENTER:
                case KeyEvent.KEYCODE_ENTER:
                    if (mEnableAutoHideKeyboard) {
                        mInputViewManager.closing();
                        requestHideSelf(0);
                        return true;
                    }
                    break;
                case KeyEvent.KEYCODE_BACK:
                    /*
                     * If 'BACK' key is pressed when the SW-keyboard is shown
                     * and the candidates view is not shown, dismiss the SW-keyboard.
                     */
                    if (isInputViewShown()) {
                        mInputViewManager.closing();
                        requestHideSelf(0);
                        return true;
                    }
                    break;
                default:
                    break;
                }
            }
        }

        return false;
    }

    /**
     * Thread for updating the candidates view
     */
    private void updatePrediction() {
        int candidates = 0;
        if (mConverter != null) {
            /* normal prediction */
            candidates = mConverter.predict(mComposingText, 0, -1);
        }
        /* update the candidates view */
        if (candidates > 0) {
            mCandidatesViewManager.displayCandidates(mConverter);
        } else {
            mCandidatesViewManager.clearCandidates();
        }
    }

    /**
     * Update the composing text.
     *
     * @param layer  {@link mComposingText}'s layer to display
     */
    private void updateComposingText(int layer) {
        /* update the candidates view */
        if (!mOptPrediction) {
            commitText(1);
            mComposingText.clear();
            if (mSymbolMode) {
                mHandler.removeMessages(MSG_PREDICTION);
                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PREDICTION), 0);
            }
        } else {
            if (mComposingText.size(1) != 0) {
                mHandler.removeMessages(MSG_PREDICTION);
                if (mCandidatesViewManager.getCurrentView().isShown()) {
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PREDICTION),
                                                PREDICTION_DELAY_MS_SHOWING_CANDIDATE);
                } else {
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PREDICTION),
                                                PREDICTION_DELAY_MS_1ST);
                }
            } else {
                mHandler.removeMessages(MSG_PREDICTION);
                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PREDICTION), 0);
            }

            /* notice to the input view */
            this.mInputViewManager.onUpdateState(this);

            /* set the text for displaying as the composing text */
            SpannableStringBuilder disp = mDisplayText;
            disp.clear();
            disp.insert(0, mComposingText.toString(layer));

            /* add decoration to the text */
            int cursor = mComposingText.getCursor(layer);
            if (disp.length() != 0) {
                if (cursor > 0 && cursor < disp.length()) {
                    disp.setSpan(SPAN_EXACT_BGCOLOR_HL, 0, cursor,
                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
                if (cursor < disp.length()) {
                    mDisplayText.setSpan(SPAN_REMAIN_BGCOLOR_HL, cursor, disp.length(),
                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    mDisplayText.setSpan(SPAN_TEXTCOLOR, 0, disp.length(),
                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                }

                disp.setSpan(SPAN_UNDERLINE, 0, disp.length(),
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }

            int displayCursor = cursor;
            if (FIX_CURSOR_TEXT_END) {
                displayCursor = (cursor == 0) ?  0 : 1;
            }
            /* update the composing text on the EditView */
            mInputConnection.setComposingText(disp, displayCursor);
        }
    }

    /**
     * Commit the composing text.
     *
     * @param layer  {@link mComposingText}'s layer to commit.
     */
    private void commitText(int layer) {
        String tmp = mComposingText.toString(layer);

        if (mOptLearning && mConverter != null && tmp.length() > 0) {
            WnnWord word = new WnnWord(tmp, tmp);
            mConverter.learn(word);
        }

        mInputConnection.commitText(tmp, (FIX_CURSOR_TEXT_END ? 1 : tmp.length()));
        mCandidatesViewManager.clearCandidates();
    }

    /**
     * Commit a word
     *
     * @param word          A word to commit
     * @param withSpace     Append a space after the word if {@code true}.
     */
    private void commitText(WnnWord word, boolean withSpace) {

        if (mOptLearning && mConverter != null) {
            mConverter.learn(word);
        }

        mInputConnection.commitText(word.candidate, (FIX_CURSOR_TEXT_END ? 1 : word.candidate.length()));

        if (withSpace) {
            commitText(" ");
        }
    }

    /**
     * Commit a string
     * <br>
     * The string is not registered into the learning dictionary.
     *
     * @param str  A string to commit
     */
    private void commitText(String str) {
        mInputConnection.commitText(str, (FIX_CURSOR_TEXT_END ? 1 : str.length()));
        mCandidatesViewManager.clearCandidates();
    }

    /**
     * Dismiss the pop-up keyboard
     */
    protected void dismissPopupKeyboard() {
        DefaultSoftKeyboardEN kbd = (DefaultSoftKeyboardEN)mInputViewManager;
        if (kbd != null) {
            kbd.dismissPopupKeyboard();
        }
    }

    /**
     * Display current meta-key state.
     */
    private void updateMetaKeyStateDisplay() {
        int mode = 0;
        if(mHardShift == 0 && mHardAlt == 0){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_OFF;
        }else if(mHardShift == 1 && mHardAlt == 0){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_ON_ALT_OFF;
        }else if(mHardShift == 2  && mHardAlt == 0){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_LOCK_ALT_OFF;
        }else if(mHardShift == 0 && mHardAlt == 1){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_ON;
        }else if(mHardShift == 0 && mHardAlt == 2){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_LOCK;
        }else if(mHardShift == 1 && mHardAlt == 1){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_ON_ALT_ON;
        }else if(mHardShift == 1 && mHardAlt == 2){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_ON_ALT_LOCK;
        }else if(mHardShift == 2 && mHardAlt == 1){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_LOCK_ALT_ON;
        }else if(mHardShift == 2 && mHardAlt == 2){
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_LOCK_ALT_LOCK;
        }else{
            mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_OFF;
        }

        ((DefaultSoftKeyboard) mInputViewManager).updateIndicator(mode);
    }

    /**
     * Handling KeyEvent(KEYUP)
     * <br>
     * This method is called from {@link #onEvent()}.
     *
     * @param ev   An up key event
     */
    private void onKeyUpEvent(KeyEvent ev) {
        int key = ev.getKeyCode();
        if(!mShiftPressing){
            if(key == KeyEvent.KEYCODE_SHIFT_LEFT || key == KeyEvent.KEYCODE_SHIFT_RIGHT){
                mHardShift = 0;
                mShiftPressing = true;
                updateMetaKeyStateDisplay();
            }
        }
        if(!mAltPressing ){
            if(key == KeyEvent.KEYCODE_ALT_LEFT || key == KeyEvent.KEYCODE_ALT_RIGHT){
                mHardAlt = 0;
                mAltPressing   = true;
                updateMetaKeyStateDisplay();
            }
        }
    }
    /**
     * Fits an editor info.
     *
     * @param preferences  The preference data.
     * @param info          The editor info.
     */
    private void fitInputType(SharedPreferences preference, EditorInfo info) {
        if (info.inputType == EditorInfo.TYPE_NULL) {
            mDirectInputMode = true;
            return;
        }

        mEnableAutoHideKeyboard = false;

        /* set prediction & spell correction mode */
        mOptPrediction      = preference.getBoolean("opt_en_prediction", true);
        mOptSpellCorrection = preference.getBoolean("opt_en_spell_correction", true);
        mOptLearning        = preference.getBoolean("opt_en_enable_learning", true);

        /* prediction on/off */
        switch (info.inputType & EditorInfo.TYPE_MASK_CLASS) {
        case EditorInfo.TYPE_CLASS_NUMBER:
        case EditorInfo.TYPE_CLASS_DATETIME:
        case EditorInfo.TYPE_CLASS_PHONE:
            mOptPrediction = false;
            mOptLearning = false;
            break;

        case EditorInfo.TYPE_CLASS_TEXT:
            switch (info.inputType & EditorInfo.TYPE_MASK_VARIATION) {
            case EditorInfo.TYPE_TEXT_VARIATION_PASSWORD:
            case EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
                mOptLearning = false;
                mOptPrediction = false;
                break;

            case EditorInfo.TYPE_TEXT_VARIATION_PHONETIC:
                mOptLearning = false;
                mOptPrediction = false;
                break;
            default:
                break;
            }
        }

        /* doesn't learn any word if it is not prediction mode */
        if (!mOptPrediction) {
            mOptLearning = false;
        }

        /* set engine's mode */
        if (mOptSpellCorrection) {
            mConverterEN.setDictionary(OpenWnnEngineEN.DICT_FOR_CORRECT_MISTYPE);
        } else {
            mConverterEN.setDictionary(OpenWnnEngineEN.DICT_DEFAULT);
        }
        checkTutorial(info.privateImeOptions);
    }

    /**
     * Check and start the tutorial if it is the tutorial mode.
     *
     * @param privateImeOptions IME's options
     */
    private void checkTutorial(String privateImeOptions) {
        if (privateImeOptions == null) return;
        if (privateImeOptions.equals("com.google.android.setupwizard:ShowTutorial")) {
            if ((mTutorial == null) && mEnableTutorial) startTutorial();
        } else if (privateImeOptions.equals("com.google.android.setupwizard:HideTutorial")) {
            if (mTutorial != null) {
                if (mTutorial.close()) {
                    mTutorial = null;
                }
            }
        }
    }

    /**
     * Start the tutorial
     */
    private void startTutorial() {
        DefaultSoftKeyboardEN inputManager = ((DefaultSoftKeyboardEN) mInputViewManager);
        View v = inputManager.getKeyboardView();
        v.setOnTouchListener(new View.OnTouchListener() {
				public boolean onTouch(View v, MotionEvent event) {
					return true;
				}});
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_TUTORIAL), 500);
    }

    /**
     * Close the tutorial
     */
    public void tutorialDone() {
        mTutorial = null;
    }

    /** @see OpenWnn#close */
    @Override protected void close() {
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLOSE), 0);
    }
}
