/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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 com.android.inputmethod.latin;

import android.inputmethodservice.InputMethodService;
import android.text.SpannableString;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;

import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.research.ResearchLogger;

import java.util.Locale;
import java.util.regex.Pattern;

/**
 * Enrichment class for InputConnection to simplify interaction and add functionality.
 *
 * This class serves as a wrapper to be able to simply add hooks to any calls to the underlying
 * InputConnection. It also keeps track of a number of things to avoid having to call upon IPC
 * all the time to find out what text is in the buffer, when we need it to determine caps mode
 * for example.
 */
public final class RichInputConnection {
    private static final String TAG = RichInputConnection.class.getSimpleName();
    private static final boolean DBG = false;
    private static final boolean DEBUG_PREVIOUS_TEXT = false;
    private static final boolean DEBUG_BATCH_NESTING = false;
    // Provision for a long word pair and a separator
    private static final int LOOKBACK_CHARACTER_NUM = Constants.Dictionary.MAX_WORD_LENGTH * 2 + 1;
    private static final Pattern spaceRegex = Pattern.compile("\\s+");
    private static final int INVALID_CURSOR_POSITION = -1;

    /**
     * This variable contains the value LatinIME thinks the cursor position should be at now.
     * This is a few steps in advance of what the TextView thinks it is, because TextView will
     * only know after the IPC calls gets through.
     */
    private int mCurrentCursorPosition = INVALID_CURSOR_POSITION; // in chars, not code points
    /**
     * This contains the committed text immediately preceding the cursor and the composing
     * text if any. It is refreshed when the cursor moves by calling upon the TextView.
     */
    private final StringBuilder mCommittedTextBeforeComposingText = new StringBuilder();
    /**
     * This contains the currently composing text, as LatinIME thinks the TextView is seeing it.
     */
    private final StringBuilder mComposingText = new StringBuilder();
    // A hint on how many characters to cache from the TextView. A good value of this is given by
    // how many characters we need to be able to almost always find the caps mode.
    private static final int DEFAULT_TEXT_CACHE_SIZE = 100;

    private final InputMethodService mParent;
    InputConnection mIC;
    int mNestLevel;
    public RichInputConnection(final InputMethodService parent) {
        mParent = parent;
        mIC = null;
        mNestLevel = 0;
    }

    private void checkConsistencyForDebug() {
        final ExtractedTextRequest r = new ExtractedTextRequest();
        r.hintMaxChars = 0;
        r.hintMaxLines = 0;
        r.token = 1;
        r.flags = 0;
        final ExtractedText et = mIC.getExtractedText(r, 0);
        final CharSequence beforeCursor = getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE, 0);
        final StringBuilder internal = new StringBuilder().append(mCommittedTextBeforeComposingText)
                .append(mComposingText);
        if (null == et || null == beforeCursor) return;
        final int actualLength = Math.min(beforeCursor.length(), internal.length());
        if (internal.length() > actualLength) {
            internal.delete(0, internal.length() - actualLength);
        }
        final String reference = (beforeCursor.length() <= actualLength) ? beforeCursor.toString()
                : beforeCursor.subSequence(beforeCursor.length() - actualLength,
                        beforeCursor.length()).toString();
        if (et.selectionStart != mCurrentCursorPosition
                || !(reference.equals(internal.toString()))) {
            final String context = "Expected cursor position = " + mCurrentCursorPosition
                    + "\nActual cursor position = " + et.selectionStart
                    + "\nExpected text = " + internal.length() + " " + internal
                    + "\nActual text = " + reference.length() + " " + reference;
            ((LatinIME)mParent).debugDumpStateAndCrashWithException(context);
        } else {
            Log.e(TAG, Utils.getStackTrace(2));
            Log.e(TAG, "Exp <> Actual : " + mCurrentCursorPosition + " <> " + et.selectionStart);
        }
    }

    public void beginBatchEdit() {
        if (++mNestLevel == 1) {
            mIC = mParent.getCurrentInputConnection();
            if (null != mIC) {
                mIC.beginBatchEdit();
            }
        } else {
            if (DBG) {
                throw new RuntimeException("Nest level too deep");
            } else {
                Log.e(TAG, "Nest level too deep : " + mNestLevel);
            }
        }
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
    }

    public void endBatchEdit() {
        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
        if (--mNestLevel == 0 && null != mIC) {
            mIC.endBatchEdit();
        }
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
    }

    public void resetCachesUponCursorMove(final int newCursorPosition) {
        mCurrentCursorPosition = newCursorPosition;
        mComposingText.setLength(0);
        mCommittedTextBeforeComposingText.setLength(0);
        final CharSequence textBeforeCursor = getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE, 0);
        if (null != textBeforeCursor) mCommittedTextBeforeComposingText.append(textBeforeCursor);
        if (null != mIC) {
            mIC.finishComposingText();
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_finishComposingText();
            }
        }
    }

    private void checkBatchEdit() {
        if (mNestLevel != 1) {
            // TODO: exception instead
            Log.e(TAG, "Batch edit level incorrect : " + mNestLevel);
            Log.e(TAG, Utils.getStackTrace(4));
        }
    }

    public void finishComposingText() {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        mCommittedTextBeforeComposingText.append(mComposingText);
        mCurrentCursorPosition += mComposingText.length();
        mComposingText.setLength(0);
        if (null != mIC) {
            mIC.finishComposingText();
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_finishComposingText();
            }
        }
    }

    public void commitText(final CharSequence text, final int i) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        mCommittedTextBeforeComposingText.append(text);
        mCurrentCursorPosition += text.length() - mComposingText.length();
        mComposingText.setLength(0);
        if (null != mIC) {
            mIC.commitText(text, i);
        }
    }

    public CharSequence getSelectedText(final int flags) {
        if (null == mIC) return null;
        return mIC.getSelectedText(flags);
    }

    /**
     * Gets the caps modes we should be in after this specific string.
     *
     * This returns a bit set of TextUtils#CAP_MODE_*, masked by the inputType argument.
     * This method also supports faking an additional space after the string passed in argument,
     * to support cases where a space will be added automatically, like in phantom space
     * state for example.
     * Note that for English, we are using American typography rules (which are not specific to
     * American English, it's just the most common set of rules for English).
     *
     * @param inputType a mask of the caps modes to test for.
     * @param locale what language should be considered.
     * @param hasSpaceBefore if we should consider there should be a space after the string.
     * @return the caps modes that should be on as a set of bits
     */
    public int getCursorCapsMode(final int inputType, final Locale locale,
            final boolean hasSpaceBefore) {
        mIC = mParent.getCurrentInputConnection();
        if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
        if (!TextUtils.isEmpty(mComposingText)) {
            if (hasSpaceBefore) {
                // If we have some composing text and a space before, then we should have
                // MODE_CHARACTERS and MODE_WORDS on.
                return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & inputType;
            } else {
                // We have some composing text - we should be in MODE_CHARACTERS only.
                return TextUtils.CAP_MODE_CHARACTERS & inputType;
            }
        }
        // TODO: this will generally work, but there may be cases where the buffer contains SOME
        // information but not enough to determine the caps mode accurately. This may happen after
        // heavy pressing of delete, for example DEFAULT_TEXT_CACHE_SIZE - 5 times or so.
        // getCapsMode should be updated to be able to return a "not enough info" result so that
        // we can get more context only when needed.
        if (TextUtils.isEmpty(mCommittedTextBeforeComposingText) && 0 != mCurrentCursorPosition) {
            mCommittedTextBeforeComposingText.append(
                    getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE, 0));
        }
        // This never calls InputConnection#getCapsMode - in fact, it's a static method that
        // never blocks or initiates IPC.
        return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale,
                hasSpaceBefore);
    }

    public int getCodePointBeforeCursor() {
        if (mCommittedTextBeforeComposingText.length() < 1) return Constants.NOT_A_CODE;
        return Character.codePointBefore(mCommittedTextBeforeComposingText,
                mCommittedTextBeforeComposingText.length());
    }

    public CharSequence getTextBeforeCursor(final int i, final int j) {
        // TODO: use mCommittedTextBeforeComposingText if possible to improve performance
        mIC = mParent.getCurrentInputConnection();
        if (null != mIC) return mIC.getTextBeforeCursor(i, j);
        return null;
    }

    public CharSequence getTextAfterCursor(final int i, final int j) {
        mIC = mParent.getCurrentInputConnection();
        if (null != mIC) return mIC.getTextAfterCursor(i, j);
        return null;
    }

    public void deleteSurroundingText(final int i, final int j) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        final int remainingChars = mComposingText.length() - i;
        if (remainingChars >= 0) {
            mComposingText.setLength(remainingChars);
        } else {
            mComposingText.setLength(0);
            // Never cut under 0
            final int len = Math.max(mCommittedTextBeforeComposingText.length()
                    + remainingChars, 0);
            mCommittedTextBeforeComposingText.setLength(len);
        }
        if (mCurrentCursorPosition > i) {
            mCurrentCursorPosition -= i;
        } else {
            mCurrentCursorPosition = 0;
        }
        if (null != mIC) {
            mIC.deleteSurroundingText(i, j);
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_deleteSurroundingText(i, j);
            }
        }
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
    }

    public void performEditorAction(final int actionId) {
        mIC = mParent.getCurrentInputConnection();
        if (null != mIC) {
            mIC.performEditorAction(actionId);
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_performEditorAction(actionId);
            }
        }
    }

    public void sendKeyEvent(final KeyEvent keyEvent) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
            if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
            // This method is only called for enter or backspace when speaking to old applications
            // (target SDK <= 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)), or for digits.
            // When talking to new applications we never use this method because it's inherently
            // racy and has unpredictable results, but for backward compatibility we continue
            // sending the key events for only Enter and Backspace because some applications
            // mistakenly catch them to do some stuff.
            switch (keyEvent.getKeyCode()) {
            case KeyEvent.KEYCODE_ENTER:
                mCommittedTextBeforeComposingText.append("\n");
                mCurrentCursorPosition += 1;
                break;
            case KeyEvent.KEYCODE_DEL:
                if (0 == mComposingText.length()) {
                    if (mCommittedTextBeforeComposingText.length() > 0) {
                        mCommittedTextBeforeComposingText.delete(
                                mCommittedTextBeforeComposingText.length() - 1,
                                mCommittedTextBeforeComposingText.length());
                    }
                } else {
                    mComposingText.delete(mComposingText.length() - 1, mComposingText.length());
                }
                if (mCurrentCursorPosition > 0) mCurrentCursorPosition -= 1;
                break;
            case KeyEvent.KEYCODE_UNKNOWN:
                if (null != keyEvent.getCharacters()) {
                    mCommittedTextBeforeComposingText.append(keyEvent.getCharacters());
                    mCurrentCursorPosition += keyEvent.getCharacters().length();
                }
                break;
            default:
                final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1);
                mCommittedTextBeforeComposingText.append(text);
                mCurrentCursorPosition += text.length();
                break;
            }
        }
        if (null != mIC) {
            mIC.sendKeyEvent(keyEvent);
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_sendKeyEvent(keyEvent);
            }
        }
    }

    public void setComposingRegion(final int start, final int end) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        mCurrentCursorPosition = end;
        final CharSequence textBeforeCursor =
                getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE + (end - start), 0);
        mCommittedTextBeforeComposingText.setLength(0);
        if (!TextUtils.isEmpty(textBeforeCursor)) {
            final int indexOfStartOfComposingText =
                    Math.max(textBeforeCursor.length() - (end - start), 0);
            mComposingText.append(textBeforeCursor.subSequence(indexOfStartOfComposingText,
                    textBeforeCursor.length()));
            mCommittedTextBeforeComposingText.append(
                    textBeforeCursor.subSequence(0, indexOfStartOfComposingText));
        }
        if (null != mIC) {
            mIC.setComposingRegion(start, end);
        }
    }

    public void setComposingText(final CharSequence text, final int i) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        mCurrentCursorPosition += text.length() - mComposingText.length();
        mComposingText.setLength(0);
        mComposingText.append(text);
        // TODO: support values of i != 1. At this time, this is never called with i != 1.
        if (null != mIC) {
            mIC.setComposingText(text, i);
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_setComposingText(text, i);
            }
        }
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
    }

    public void setSelection(final int from, final int to) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        if (null != mIC) {
            mIC.setSelection(from, to);
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_setSelection(from, to);
            }
        }
        mCurrentCursorPosition = from;
        mCommittedTextBeforeComposingText.setLength(0);
        mCommittedTextBeforeComposingText.append(getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE, 0));
    }

    public void commitCorrection(final CorrectionInfo correctionInfo) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        // This has no effect on the text field and does not change its content. It only makes
        // TextView flash the text for a second based on indices contained in the argument.
        if (null != mIC) {
            mIC.commitCorrection(correctionInfo);
        }
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
    }

    public void commitCompletion(final CompletionInfo completionInfo) {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
        CharSequence text = completionInfo.getText();
        // text should never be null, but just in case, it's better to insert nothing than to crash
        if (null == text) text = "";
        mCommittedTextBeforeComposingText.append(text);
        mCurrentCursorPosition += text.length() - mComposingText.length();
        mComposingText.setLength(0);
        if (null != mIC) {
            mIC.commitCompletion(completionInfo);
            if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
                ResearchLogger.richInputConnection_commitCompletion(completionInfo);
            }
        }
        if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
    }

    @SuppressWarnings("unused")
    public String getNthPreviousWord(final String sentenceSeperators, final int n) {
        mIC = mParent.getCurrentInputConnection();
        if (null == mIC) return null;
        final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
        if (DEBUG_PREVIOUS_TEXT && null != prev) {
            final int checkLength = LOOKBACK_CHARACTER_NUM - 1;
            final String reference = prev.length() <= checkLength ? prev.toString()
                    : prev.subSequence(prev.length() - checkLength, prev.length()).toString();
            final StringBuilder internal = new StringBuilder()
                    .append(mCommittedTextBeforeComposingText).append(mComposingText);
            if (internal.length() > checkLength) {
                internal.delete(0, internal.length() - checkLength);
                if (!(reference.equals(internal.toString()))) {
                    final String context =
                            "Expected text = " + internal + "\nActual text = " + reference;
                    ((LatinIME)mParent).debugDumpStateAndCrashWithException(context);
                }
            }
        }
        return getNthPreviousWord(prev, sentenceSeperators, n);
    }

    /**
     * Represents a range of text, relative to the current cursor position.
     */
    public static final class Range {
        /** Characters before selection start */
        public final int mCharsBefore;

        /**
         * Characters after selection start, including one trailing word
         * separator.
         */
        public final int mCharsAfter;

        /** The actual characters that make up a word */
        public final CharSequence mWord;

        public Range(int charsBefore, int charsAfter, CharSequence word) {
            if (charsBefore < 0 || charsAfter < 0) {
                throw new IndexOutOfBoundsException();
            }
            this.mCharsBefore = charsBefore;
            this.mCharsAfter = charsAfter;
            this.mWord = word;
        }
    }

    private static boolean isSeparator(int code, String sep) {
        return sep.indexOf(code) != -1;
    }

    // Get the nth word before cursor. n = 1 retrieves the word immediately before the cursor,
    // n = 2 retrieves the word before that, and so on. This splits on whitespace only.
    // Also, it won't return words that end in a separator (if the nth word before the cursor
    // ends in a separator, it returns null).
    // Example :
    // (n = 1) "abc def|" -> def
    // (n = 1) "abc def |" -> def
    // (n = 1) "abc def. |" -> null
    // (n = 1) "abc def . |" -> null
    // (n = 2) "abc def|" -> abc
    // (n = 2) "abc def |" -> abc
    // (n = 2) "abc def. |" -> abc
    // (n = 2) "abc def . |" -> def
    // (n = 2) "abc|" -> null
    // (n = 2) "abc |" -> null
    // (n = 2) "abc. def|" -> null
    public static String getNthPreviousWord(final CharSequence prev,
            final String sentenceSeperators, final int n) {
        if (prev == null) return null;
        final String[] w = spaceRegex.split(prev);

        // If we can't find n words, or we found an empty word, return null.
        if (w.length < n) return null;
        final String nthPrevWord = w[w.length - n];
        final int length = nthPrevWord.length();
        if (length <= 0) return null;

        // If ends in a separator, return null
        final char lastChar = nthPrevWord.charAt(length - 1);
        if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;

        return nthPrevWord;
    }

    /**
     * @param separators characters which may separate words
     * @return the word that surrounds the cursor, including up to one trailing
     *   separator. For example, if the field contains "he|llo world", where |
     *   represents the cursor, then "hello " will be returned.
     */
    public CharSequence getWordAtCursor(String separators) {
        // getWordRangeAtCursor returns null if the connection is null
        Range r = getWordRangeAtCursor(separators, 0);
        return (r == null) ? null : r.mWord;
    }

    /**
     * Returns the text surrounding the cursor.
     *
     * @param sep a string of characters that split words.
     * @param additionalPrecedingWordsCount the number of words before the current word that should
     *   be included in the returned range
     * @return a range containing the text surrounding the cursor
     */
    public Range getWordRangeAtCursor(final String sep, final int additionalPrecedingWordsCount) {
        mIC = mParent.getCurrentInputConnection();
        if (mIC == null || sep == null) {
            return null;
        }
        final CharSequence before = mIC.getTextBeforeCursor(1000,
                InputConnection.GET_TEXT_WITH_STYLES);
        final CharSequence after = mIC.getTextAfterCursor(1000,
                InputConnection.GET_TEXT_WITH_STYLES);
        if (before == null || after == null) {
            return null;
        }

        // Going backward, alternate skipping non-separators and separators until enough words
        // have been read.
        int count = additionalPrecedingWordsCount;
        int startIndexInBefore = before.length();
        boolean isStoppingAtWhitespace = true;  // toggles to indicate what to stop at
        while (true) { // see comments below for why this is guaranteed to halt
            while (startIndexInBefore > 0) {
                final int codePoint = Character.codePointBefore(before, startIndexInBefore);
                if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) {
                    break;  // inner loop
                }
                --startIndexInBefore;
                if (Character.isSupplementaryCodePoint(codePoint)) {
                    --startIndexInBefore;
                }
            }
            // isStoppingAtWhitespace is true every other time through the loop,
            // so additionalPrecedingWordsCount is guaranteed to become < 0, which
            // guarantees outer loop termination
            if (isStoppingAtWhitespace && (--count < 0)) {
                break;  // outer loop
            }
            isStoppingAtWhitespace = !isStoppingAtWhitespace;
        }

        // Find last word separator after the cursor
        int endIndexInAfter = -1;
        while (++endIndexInAfter < after.length()) {
            final int codePoint = Character.codePointAt(after, endIndexInAfter);
            if (isSeparator(codePoint, sep)) {
                break;
            }
            if (Character.isSupplementaryCodePoint(codePoint)) {
                ++endIndexInAfter;
            }
        }

        final SpannableString word = new SpannableString(TextUtils.concat(
                before.subSequence(startIndexInBefore, before.length()),
                after.subSequence(0, endIndexInAfter)));
        return new Range(before.length() - startIndexInBefore, endIndexInAfter, word);
    }

    public boolean isCursorTouchingWord(final SettingsValues settingsValues) {
        final CharSequence before = getTextBeforeCursor(1, 0);
        final CharSequence after = getTextAfterCursor(1, 0);
        if (!TextUtils.isEmpty(before) && !settingsValues.isWordSeparator(before.charAt(0))
                && !settingsValues.isWordConnector(before.charAt(0))) {
            return true;
        }
        if (!TextUtils.isEmpty(after) && !settingsValues.isWordSeparator(after.charAt(0))
                && !settingsValues.isWordConnector(after.charAt(0))) {
            return true;
        }
        return false;
    }

    public void removeTrailingSpace() {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        final CharSequence lastOne = getTextBeforeCursor(1, 0);
        if (lastOne != null && lastOne.length() == 1
                && lastOne.charAt(0) == Constants.CODE_SPACE) {
            deleteSurroundingText(1, 0);
        }
    }

    public boolean sameAsTextBeforeCursor(final CharSequence text) {
        final CharSequence beforeText = getTextBeforeCursor(text.length(), 0);
        return TextUtils.equals(text, beforeText);
    }

    /* (non-javadoc)
     * Returns the word before the cursor if the cursor is at the end of a word, null otherwise
     */
    public CharSequence getWordBeforeCursorIfAtEndOfWord(final SettingsValues settings) {
        // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
        // separator or end of line/text)
        // Example: "test|"<EOL> "te|st" get rejected here
        final CharSequence textAfterCursor = getTextAfterCursor(1, 0);
        if (!TextUtils.isEmpty(textAfterCursor)
                && !settings.isWordSeparator(textAfterCursor.charAt(0))) return null;

        // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe)
        // Example: " -|" gets rejected here but "e-|" and "e|" are okay
        CharSequence word = getWordAtCursor(settings.mWordSeparators);
        // We don't suggest on leading single quotes, so we have to remove them from the word if
        // it starts with single quotes.
        while (!TextUtils.isEmpty(word) && Constants.CODE_SINGLE_QUOTE == word.charAt(0)) {
            word = word.subSequence(1, word.length());
        }
        if (TextUtils.isEmpty(word)) return null;
        // Find the last code point of the string
        final int lastCodePoint = Character.codePointBefore(word, word.length());
        // If for some reason the text field contains non-unicode binary data, or if the
        // charsequence is exactly one char long and the contents is a low surrogate, return null.
        if (!Character.isDefined(lastCodePoint)) return null;
        // Bail out if the cursor is not at the end of a word (cursor must be preceded by
        // non-whitespace, non-separator, non-start-of-text)
        // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
        if (settings.isWordSeparator(lastCodePoint)) return null;
        final char firstChar = word.charAt(0); // we just tested that word is not empty
        if (word.length() == 1 && !Character.isLetter(firstChar)) return null;

        // We don't restart suggestion if the first character is not a letter, because we don't
        // start composing when the first character is not a letter.
        if (!Character.isLetter(firstChar)) return null;

        return word;
    }

    public boolean revertDoubleSpacePeriod() {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        // Here we test whether we indeed have a period and a space before us. This should not
        // be needed, but it's there just in case something went wrong.
        final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
        final String periodSpace = ". ";
        if (!periodSpace.equals(textBeforeCursor)) {
            // Theoretically we should not be coming here if there isn't ". " before the
            // cursor, but the application may be changing the text while we are typing, so
            // anything goes. We should not crash.
            Log.d(TAG, "Tried to revert double-space combo but we didn't find "
                    + "\"" + periodSpace + "\" just before the cursor.");
            return false;
        }
        deleteSurroundingText(2, 0);
        final String doubleSpace = "  ";
        commitText(doubleSpace, 1);
        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
            ResearchLogger.richInputConnection_revertDoubleSpacePeriod();
        }
        return true;
    }

    public boolean revertSwapPunctuation() {
        if (DEBUG_BATCH_NESTING) checkBatchEdit();
        // Here we test whether we indeed have a space and something else before us. This should not
        // be needed, but it's there just in case something went wrong.
        final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
        // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
        // enter surrogate pairs this code will have been removed.
        if (TextUtils.isEmpty(textBeforeCursor)
                || (Constants.CODE_SPACE != textBeforeCursor.charAt(1))) {
            // We may only come here if the application is changing the text while we are typing.
            // This is quite a broken case, but not logically impossible, so we shouldn't crash,
            // but some debugging log may be in order.
            Log.d(TAG, "Tried to revert a swap of punctuation but we didn't "
                    + "find a space just before the cursor.");
            return false;
        }
        deleteSurroundingText(2, 0);
        final String text = " " + textBeforeCursor.subSequence(0, 1);
        commitText(text, 1);
        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
            ResearchLogger.richInputConnection_revertSwapPunctuation();
        }
        return true;
    }

    /**
     * Heuristic to determine if this is an expected update of the cursor.
     *
     * Sometimes updates to the cursor position are late because of their asynchronous nature.
     * This method tries to determine if this update is one, based on the values of the cursor
     * position in the update, and the currently expected position of the cursor according to
     * LatinIME's internal accounting. If this is not a belated expected update, then it should
     * mean that the user moved the cursor explicitly.
     * This is quite robust, but of course it's not perfect. In particular, it will fail in the
     * case we get an update A, the user types in N characters so as to move the cursor to A+N but
     * we don't get those, and then the user places the cursor between A and A+N, and we get only
     * this update and not the ones in-between. This is almost impossible to achieve even trying
     * very very hard.
     *
     * @param oldSelStart The value of the old cursor position in the update.
     * @param newSelStart The value of the new cursor position in the update.
     * @return whether this is a belated expected update or not.
     */
    public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart) {
        // If this is an update that arrives at our expected position, it's a belated update.
        if (newSelStart == mCurrentCursorPosition) return true;
        // If this is an update that moves the cursor from our expected position, it must be
        // an explicit move.
        if (oldSelStart == mCurrentCursorPosition) return false;
        // The following returns true if newSelStart is between oldSelStart and
        // mCurrentCursorPosition. We assume that if the updated position is between the old
        // position and the expected position, then it must be a belated update.
        return (newSelStart - oldSelStart) * (mCurrentCursorPosition - newSelStart) >= 0;
    }

    /**
     * Looks at the text just before the cursor to find out if it looks like a URL.
     *
     * The weakest point here is, if we don't have enough text bufferized, we may fail to realize
     * we are in URL situation, but other places in this class have the same limitation and it
     * does not matter too much in the practice.
     */
    public boolean textBeforeCursorLooksLikeURL() {
        return StringUtils.lastPartLooksLikeURL(mCommittedTextBeforeComposingText);
    }
}
