/*
 * Copyright (C) 2007 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 android.webkit;

import com.android.internal.widget.EditableInputConnection;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ResultReceiver;
import android.text.BoringLayout.Metrics;
import android.text.DynamicLayout;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.MovementMethod;
import android.text.method.Touch;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputConnection;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.TextView;

import java.util.ArrayList;

import junit.framework.Assert;

/**
 * WebTextView is a specialized version of EditText used by WebView
 * to overlay html textfields (and textareas) to use our standard
 * text editing.
 */
/* package */ class WebTextView extends AutoCompleteTextView
        implements AdapterView.OnItemClickListener {

    static final String LOGTAG = "webtextview";

    private WebView         mWebView;
    private boolean         mSingle;
    private int             mWidthSpec;
    private int             mHeightSpec;
    private int             mNodePointer;
    // FIXME: This is a hack for blocking unmatched key ups, in particular
    // on the enter key.  The method for blocking unmatched key ups prevents
    // the shift key from working properly.
    private boolean         mGotEnterDown;
    private int             mMaxLength;
    // Keep track of the text before the change so we know whether we actually
    // need to send down the DOM events.
    private String          mPreChange;
    private Drawable        mBackground;
    // Variables for keeping track of the touch down, to send to the WebView
    // when a drag starts
    private float           mDragStartX;
    private float           mDragStartY;
    private long            mDragStartTime;
    private boolean         mDragSent;
    // True if the most recent drag event has caused either the TextView to
    // scroll or the web page to scroll.  Gets reset after a touch down.
    private boolean         mScrolled;
    // Whether or not a selection change was generated from webkit.  If it was,
    // we do not need to pass the selection back to webkit.
    private boolean         mFromWebKit;
    // Whether or not a selection change was generated from the WebTextView
    // gaining focus.  If it is, we do not want to pass it to webkit.  This
    // selection comes from the MovementMethod, but we behave differently.  If
    // WebTextView gained focus from a touch, webkit will determine the
    // selection.
    private boolean         mFromFocusChange;
    // Whether or not a selection change was generated from setInputType.  We
    // do not want to pass this change to webkit.
    private boolean         mFromSetInputType;
    private boolean         mGotTouchDown;
    // Keep track of whether a long press has happened.  Only meaningful after
    // an ACTION_DOWN MotionEvent
    private boolean         mHasPerformedLongClick;
    private boolean         mInSetTextAndKeepSelection;
    // Array to store the final character added in onTextChanged, so that its
    // KeyEvents may be determined.
    private char[]          mCharacter = new char[1];
    // This is used to reset the length filter when on a textfield
    // with no max length.
    // FIXME: This can be replaced with TextView.NO_FILTERS if that
    // is made public/protected.
    private static final InputFilter[] NO_FILTERS = new InputFilter[0];
    // For keeping track of the fact that the delete key was pressed, so
    // we can simply pass a delete key instead of calling deleteSelection.
    private boolean mGotDelete;
    private int mDelSelStart;
    private int mDelSelEnd;

    // Keep in sync with native constant in
    // external/webkit/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp
    /* package */ static final int FORM_NOT_AUTOFILLABLE = -1;

    private boolean mAutoFillable; // Is this textview part of an autofillable form?
    private int mQueryId;
    private boolean mAutoFillProfileIsSet;
    // Used to determine whether onFocusChanged was called as a result of
    // calling remove().
    private boolean mInsideRemove;
    private class MyResultReceiver extends ResultReceiver {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            if (resultCode == InputMethodManager.RESULT_SHOWN
                    && mWebView != null) {
                mWebView.revealSelection();
            }
        }

        /**
         * @param handler
         */
        public MyResultReceiver(Handler handler) {
            super(handler);
        }
    }
    private MyResultReceiver mReceiver;

    // Types used with setType.  Keep in sync with CachedInput.h
    private static final int NORMAL_TEXT_FIELD = 0;
    private static final int TEXT_AREA = 1;
    private static final int PASSWORD = 2;
    private static final int SEARCH = 3;
    private static final int EMAIL = 4;
    private static final int NUMBER = 5;
    private static final int TELEPHONE = 6;
    private static final int URL = 7;

    private static final int AUTOFILL_FORM = 100;
    private Handler mHandler;

    /**
     * Create a new WebTextView.
     * @param   context The Context for this WebTextView.
     * @param   webView The WebView that created this.
     */
    /* package */ WebTextView(Context context, WebView webView, int autoFillQueryId) {
        super(context, null, com.android.internal.R.attr.webTextViewStyle);
        mWebView = webView;
        mMaxLength = -1;
        setAutoFillable(autoFillQueryId);
        // Turn on subpixel text, and turn off kerning, so it better matches
        // the text in webkit.
        TextPaint paint = getPaint();
        int flags = paint.getFlags() & ~Paint.DEV_KERN_TEXT_FLAG
                | Paint.SUBPIXEL_TEXT_FLAG | Paint.DITHER_FLAG;
        paint.setFlags(flags);

        // Set the text color to black, regardless of the theme.  This ensures
        // that other applications that use embedded WebViews will properly
        // display the text in password textfields.
        setTextColor(DebugFlags.DRAW_WEBTEXTVIEW ? Color.RED : Color.BLACK);
        // This helps to align the text better with the text in the web page.
        setIncludeFontPadding(false);

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case AUTOFILL_FORM:
                    mWebView.autoFillForm(mQueryId);
                    break;
                }
            }
        };
        mReceiver = new MyResultReceiver(mHandler);
    }

    public void setAutoFillable(int queryId) {
        mAutoFillable = mWebView.getSettings().getAutoFillEnabled()
                && (queryId != FORM_NOT_AUTOFILLABLE);
        mQueryId = queryId;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.isSystem()) {
            return super.dispatchKeyEvent(event);
        }
        // Treat ACTION_DOWN and ACTION MULTIPLE the same
        boolean down = event.getAction() != KeyEvent.ACTION_UP;
        int keyCode = event.getKeyCode();

        boolean isArrowKey = false;
        switch(keyCode) {
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_DPAD_DOWN:
                isArrowKey = true;
                break;
        }

        if (KeyEvent.KEYCODE_TAB == keyCode) {
            if (down) {
                onEditorAction(EditorInfo.IME_ACTION_NEXT);
            }
            return true;
        }
        Spannable text = (Spannable) getText();
        int oldStart = Selection.getSelectionStart(text);
        int oldEnd = Selection.getSelectionEnd(text);
        // Normally the delete key's dom events are sent via onTextChanged.
        // However, if the cursor is at the beginning of the field, which
        // includes the case where it has zero length, then the text is not
        // changed, so send the events immediately.
        if (KeyEvent.KEYCODE_DEL == keyCode) {
            if (oldStart == 0 && oldEnd == 0) {
                sendDomEvent(event);
                return true;
            }
            if (down) {
                mGotDelete = true;
                mDelSelStart = oldStart;
                mDelSelEnd = oldEnd;
            }
        }

        if (mSingle && (KeyEvent.KEYCODE_ENTER == keyCode
                    || KeyEvent.KEYCODE_NUMPAD_ENTER == keyCode)) {
            if (isPopupShowing()) {
                return super.dispatchKeyEvent(event);
            }
            if (!down) {
                // Hide the keyboard, since the user has just submitted this
                // form.  The submission happens thanks to the two calls
                // to sendDomEvent.
                InputMethodManager.getInstance(mContext)
                        .hideSoftInputFromWindow(getWindowToken(), 0);
                sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
                sendDomEvent(event);
            }
            return super.dispatchKeyEvent(event);
        } else if (KeyEvent.KEYCODE_DPAD_CENTER == keyCode) {
            // Note that this handles center key and trackball.
            if (isPopupShowing()) {
                return super.dispatchKeyEvent(event);
            }
            // Center key should be passed to a potential onClick
            if (!down) {
                mWebView.centerKeyPressOnTextField();
            }
            // Pass to super to handle longpress.
            return super.dispatchKeyEvent(event);
        }

        // Ensure there is a layout so arrow keys are handled properly.
        if (getLayout() == null) {
            measure(mWidthSpec, mHeightSpec);
        }

        int oldLength = text.length();
        boolean maxedOut = mMaxLength != -1 && oldLength == mMaxLength;
        // If we are at max length, and there is a selection rather than a
        // cursor, we need to store the text to compare later, since the key
        // may have changed the string.
        String oldText;
        if (maxedOut && oldEnd != oldStart) {
            oldText = text.toString();
        } else {
            oldText = "";
        }
        if (super.dispatchKeyEvent(event)) {
            // If the WebTextView handled the key it was either an alphanumeric
            // key, a delete, or a movement within the text. All of those are
            // ok to pass to javascript.

            // UNLESS there is a max length determined by the html.  In that
            // case, if the string was already at the max length, an
            // alphanumeric key will be erased by the LengthFilter,
            // so do not pass down to javascript, and instead
            // return true.  If it is an arrow key or a delete key, we can go
            // ahead and pass it down.
            if (KeyEvent.KEYCODE_ENTER == keyCode
                        || KeyEvent.KEYCODE_NUMPAD_ENTER == keyCode) {
                // For multi-line text boxes, newlines will
                // trigger onTextChanged for key down (which will send both
                // key up and key down) but not key up.
                mGotEnterDown = true;
            }
            if (maxedOut && !isArrowKey && keyCode != KeyEvent.KEYCODE_DEL) {
                if (oldEnd == oldStart) {
                    // Return true so the key gets dropped.
                    return true;
                } else if (!oldText.equals(getText().toString())) {
                    // FIXME: This makes the text work properly, but it
                    // does not pass down the key event, so it may not
                    // work for a textfield that has the type of
                    // behavior of GoogleSuggest.  That said, it is
                    // unlikely that a site would combine the two in
                    // one textfield.
                    Spannable span = (Spannable) getText();
                    int newStart = Selection.getSelectionStart(span);
                    int newEnd = Selection.getSelectionEnd(span);
                    mWebView.replaceTextfieldText(0, oldLength, span.toString(),
                            newStart, newEnd);
                    return true;
                }
            }
            /* FIXME:
             * In theory, we would like to send the events for the arrow keys.
             * However, the TextView can arbitrarily change the selection (i.e.
             * long press followed by using the trackball).  Therefore, we keep
             * in sync with the TextView via onSelectionChanged.  If we also
             * send the DOM event, we lose the correct selection.
            if (isArrowKey) {
                // Arrow key does not change the text, but we still want to send
                // the DOM events.
                sendDomEvent(event);
            }
             */
            return true;
        }
        // Ignore the key up event for newlines. This prevents
        // multiple newlines in the native textarea.
        if (mGotEnterDown && !down) {
            return true;
        }
        // if it is a navigation key, pass it to WebView
        if (isArrowKey) {
            // WebView check the trackballtime in onKeyDown to avoid calling
            // native from both trackball and key handling. As this is called
            // from WebTextView, we always want WebView to check with native.
            // Reset trackballtime to ensure it.
            mWebView.resetTrackballTime();
            return down ? mWebView.onKeyDown(keyCode, event) : mWebView
                    .onKeyUp(keyCode, event);
        }
        return false;
    }

    void ensureLayout() {
        if (getLayout() == null) {
            // Ensure we have a Layout
            measure(mWidthSpec, mHeightSpec);
            LayoutParams params = (LayoutParams) getLayoutParams();
            if (params != null) {
                layout(params.x, params.y, params.x + params.width,
                        params.y + params.height);
            }
        }
    }

    /* package */ ResultReceiver getResultReceiver() { return mReceiver; }

    /**
     *  Determine whether this WebTextView currently represents the node
     *  represented by ptr.
     *  @param  ptr Pointer to a node to compare to.
     *  @return boolean Whether this WebTextView already represents the node
     *          pointed to by ptr.
     */
    /* package */ boolean isSameTextField(int ptr) {
        return ptr == mNodePointer;
    }

    /**
     * Ensure that the underlying text field/area is lined up with the WebTextView.
     */
    private void lineUpScroll() {
        Layout layout = getLayout();
        if (mWebView != null && layout != null) {
            if (mSingle) {
                // textfields only need to be lined up horizontally.
                float maxScrollX = layout.getLineRight(0) - getWidth();
                if (DebugFlags.WEB_TEXT_VIEW) {
                    Log.v(LOGTAG, "onTouchEvent x=" + mScrollX + " y="
                            + mScrollY + " maxX=" + maxScrollX);
                }
                mWebView.scrollFocusedTextInputX(maxScrollX > 0 ?
                        mScrollX / maxScrollX : 0);
            } else {
                // textareas only need to be lined up vertically.
                mWebView.scrollFocusedTextInputY(mScrollY);
            }
        }
    }

    @Override
    protected void makeNewLayout(int w, int hintWidth, Metrics boring,
            Metrics hintBoring, int ellipsisWidth, boolean bringIntoView) {
        // Necessary to get a Layout to work with, and to do the other work that
        // makeNewLayout does.
        super.makeNewLayout(w, hintWidth, boring, hintBoring, ellipsisWidth,
                bringIntoView);

        // For fields that do not draw, create a layout which is altered so that
        // the text lines up.
        if (DebugFlags.DRAW_WEBTEXTVIEW || willNotDraw()) {
            float lineHeight = -1;
            if (mWebView != null) {
                float height = mWebView.nativeFocusCandidateLineHeight();
                if (height != -1) {
                    lineHeight = height * mWebView.getScale();
                }
            }
            CharSequence text = getText();
            // Copy from the existing Layout.
            mLayout = new WebTextViewLayout(text, text, getPaint(), mLayout.getWidth(),
                    mLayout.getAlignment(), mLayout.getSpacingMultiplier(),
                    mLayout.getSpacingAdd(), false, null, ellipsisWidth,
                    lineHeight);
        }
        lineUpScroll();
    }

    /**
     * Custom layout which figures out its line spacing.  If -1 is passed in for
     * the height, it will use the ascent and descent from the paint to
     * determine the line spacing.  Otherwise it will use the spacing provided.
     */
    private static class WebTextViewLayout extends DynamicLayout {
        private float mLineHeight;
        private float mDifference;
        public WebTextViewLayout(CharSequence base, CharSequence display,
                TextPaint paint,
                int width, Alignment align,
                float spacingMult, float spacingAdd,
                boolean includepad,
                TextUtils.TruncateAt ellipsize, int ellipsizedWidth,
                float lineHeight) {
            super(base, display, paint, width, align, spacingMult, spacingAdd,
                    includepad, ellipsize, ellipsizedWidth);
            float paintLineHeight = paint.descent() - paint.ascent();
            if (lineHeight == -1f) {
                mLineHeight = paintLineHeight;
                mDifference = 0f;
            } else {
                mLineHeight = lineHeight;
                // Through trial and error, I found this calculation to improve
                // the accuracy of line placement.
                mDifference = (lineHeight - paintLineHeight) / 2;
            }
        }

        @Override
        public int getLineTop(int line) {
            return Math.round(mLineHeight * line - mDifference);
        }
    }

    @Override public InputConnection onCreateInputConnection(
            EditorInfo outAttrs) {
        InputConnection connection = super.onCreateInputConnection(outAttrs);
        if (mWebView != null) {
            // Use the name of the textfield + the url.  Use backslash as an
            // arbitrary separator.
            outAttrs.fieldName = mWebView.nativeFocusCandidateName() + "\\"
                    + mWebView.getUrl();
        }
        return connection;
    }

    /**
     * In general, TextView makes a call to InputMethodManager.updateSelection
     * in onDraw.  However, in the general case of WebTextView, we do not draw.
     * This method is called by WebView.onDraw to take care of the part that
     * needs to be called.
     */
    /* package */ void onDrawSubstitute() {
        if (!willNotDraw()) {
            // If the WebTextView is set to draw, such as in the case of a
            // password, onDraw calls updateSelection(), so this code path is
            // unnecessary.
            return;
        }
        // This code is copied from TextView.onDraw().  That code does not get
        // executed, however, because the WebTextView does not draw, allowing
        // webkit's drawing to show through.
        InputMethodManager imm = InputMethodManager.peekInstance();
        if (imm != null && imm.isActive(this)) {
            Spannable sp = (Spannable) getText();
            int selStart = Selection.getSelectionStart(sp);
            int selEnd = Selection.getSelectionEnd(sp);
            int candStart = EditableInputConnection.getComposingSpanStart(sp);
            int candEnd = EditableInputConnection.getComposingSpanEnd(sp);
            imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
        }
        updateCursorControllerPositions();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // onDraw should only be called for password fields.  If WebTextView is
        // still drawing, but is no longer corresponding to a password field,
        // remove it.
        if (!DebugFlags.DRAW_WEBTEXTVIEW && (mWebView == null
                || !mWebView.nativeFocusCandidateIsPassword()
                || !isSameTextField(mWebView.nativeFocusCandidatePointer()))) {
            // Although calling remove() would seem to make more sense here,
            // changing it to not be a password field will make it not draw.
            // Other code will make sure that it is removed completely, but this
            // way the user will not see it.
            setInPassword(false);
        } else {
            super.onDraw(canvas);
        }
    }

    @Override
    public void onEditorAction(int actionCode) {
        switch (actionCode) {
        case EditorInfo.IME_ACTION_NEXT:
            if (mWebView.nativeMoveCursorToNextTextInput()) {
                // Preemptively rebuild the WebTextView, so that the action will
                // be set properly.
                mWebView.rebuildWebTextView();
                setDefaultSelection();
                mWebView.invalidate();
            }
            break;
        case EditorInfo.IME_ACTION_DONE:
            super.onEditorAction(actionCode);
            break;
        case EditorInfo.IME_ACTION_GO:
        case EditorInfo.IME_ACTION_SEARCH:
            // Send an enter and hide the soft keyboard
            InputMethodManager.getInstance(mContext)
                    .hideSoftInputFromWindow(getWindowToken(), 0);
            sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
                    KeyEvent.KEYCODE_ENTER));
            sendDomEvent(new KeyEvent(KeyEvent.ACTION_UP,
                    KeyEvent.KEYCODE_ENTER));

        default:
            break;
        }
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction,
            Rect previouslyFocusedRect) {
        mFromFocusChange = true;
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (focused) {
            mWebView.setActive(true);
        } else if (!mInsideRemove) {
            mWebView.setActive(false);
        }
        mFromFocusChange = false;
    }

    // AdapterView.OnItemClickListener implementation

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (id == 0 && position == 0) {
            // Blank out the text box while we wait for WebCore to fill the form.
            replaceText("");
            WebSettings settings = mWebView.getSettings();
            if (mAutoFillProfileIsSet) {
                // Call a webview method to tell WebCore to autofill the form.
                mWebView.autoFillForm(mQueryId);
            } else {
                // There is no autofill profile setup yet and the user has
                // elected to try and set one up. Call through to the
                // embedder to action that.
                mWebView.getWebChromeClient().setupAutoFill(
                        mHandler.obtainMessage(AUTOFILL_FORM));
            }
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        lineUpScroll();
    }

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {
        if (!mFromWebKit && !mFromFocusChange && !mFromSetInputType
                && mWebView != null && !mInSetTextAndKeepSelection) {
            if (DebugFlags.WEB_TEXT_VIEW) {
                Log.v(LOGTAG, "onSelectionChanged selStart=" + selStart
                        + " selEnd=" + selEnd);
            }
            mWebView.setSelection(selStart, selEnd);
            lineUpScroll();
        }
    }

    @Override
    protected void onTextChanged(CharSequence s,int start,int before,int count){
        super.onTextChanged(s, start, before, count);
        String postChange = s.toString();
        // Prevent calls to setText from invoking onTextChanged (since this will
        // mean we are on a different textfield).  Also prevent the change when
        // going from a textfield with a string of text to one with a smaller
        // limit on text length from registering the onTextChanged event.
        if (mPreChange == null || mPreChange.equals(postChange) ||
                (mMaxLength > -1 && mPreChange.length() > mMaxLength &&
                mPreChange.substring(0, mMaxLength).equals(postChange))) {
            return;
        }
        mPreChange = postChange;
        if (0 == count) {
            if (before > 0) {
                // For this and all changes to the text, update our cache
                updateCachedTextfield();
                if (mGotDelete) {
                    mGotDelete = false;
                    int oldEnd = start + before;
                    if (mDelSelEnd == oldEnd
                            && (mDelSelStart == start
                            || (mDelSelStart == oldEnd && before == 1))) {
                        // If the selection is set up properly before the
                        // delete, send the DOM events.
                        sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
                                KeyEvent.KEYCODE_DEL));
                        sendDomEvent(new KeyEvent(KeyEvent.ACTION_UP,
                                KeyEvent.KEYCODE_DEL));
                        return;
                    }
                }
                // This was simply a delete or a cut, so just delete the
                // selection.
                mWebView.deleteSelection(start, start + before);
            }
            mGotDelete = false;
            // before should never be negative, so whether it was a cut
            // (handled above), or before is 0, in which case nothing has
            // changed, we should return.
            return;
        }
        // Ensure that this flag gets cleared, since with autocorrect on, a
        // delete key press may have a more complex result than deleting one
        // character or the existing selection, so it will not get cleared
        // above.
        mGotDelete = false;
        // Find the last character being replaced.  If it can be represented by
        // events, we will pass them to native (after replacing the beginning
        // of the changed text), so we can see javascript events.
        // Otherwise, replace the text being changed (including the last
        // character) in the textfield.
        TextUtils.getChars(s, start + count - 1, start + count, mCharacter, 0);
        KeyCharacterMap kmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
        KeyEvent[] events = kmap.getEvents(mCharacter);
        boolean cannotUseKeyEvents = null == events;
        int charactersFromKeyEvents = cannotUseKeyEvents ? 0 : 1;
        if (count > 1 || cannotUseKeyEvents) {
            String replace = s.subSequence(start,
                    start + count - charactersFromKeyEvents).toString();
            mWebView.replaceTextfieldText(start, start + before, replace,
                    start + count - charactersFromKeyEvents,
                    start + count - charactersFromKeyEvents);
        } else {
            // This corrects the selection which may have been affected by the
            // trackball or auto-correct.
            if (DebugFlags.WEB_TEXT_VIEW) {
                Log.v(LOGTAG, "onTextChanged start=" + start
                        + " start + before=" + (start + before));
            }
            if (!mInSetTextAndKeepSelection) {
                mWebView.setSelection(start, start + before);
            }
        }
        if (!cannotUseKeyEvents) {
            int length = events.length;
            for (int i = 0; i < length; i++) {
                // We never send modifier keys to native code so don't send them
                // here either.
                if (!KeyEvent.isModifierKey(events[i].getKeyCode())) {
                    sendDomEvent(events[i]);
                }
            }
        }
        updateCachedTextfield();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            super.onTouchEvent(event);
            // This event may be the start of a drag, so store it to pass to the
            // WebView if it is.
            mDragStartX = event.getX();
            mDragStartY = event.getY();
            mDragStartTime = event.getEventTime();
            mDragSent = false;
            mScrolled = false;
            mGotTouchDown = true;
            mHasPerformedLongClick = false;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mHasPerformedLongClick) {
                mGotTouchDown = false;
                return false;
            }
            int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
            Spannable buffer = getText();
            int initialScrollX = Touch.getInitialScrollX(this, buffer);
            int initialScrollY = Touch.getInitialScrollY(this, buffer);
            super.onTouchEvent(event);
            int dx = Math.abs(mScrollX - initialScrollX);
            int dy = Math.abs(mScrollY - initialScrollY);
            // Use a smaller slop when checking to see if we've moved far enough
            // to scroll the text, because experimentally, slop has shown to be
            // to big for the case of a small textfield.
            int smallerSlop = slop/2;
            if (dx > smallerSlop || dy > smallerSlop) {
                // Scrolling is handled in onScrollChanged.
                mScrolled = true;
                cancelLongPress();
                return true;
            }
            if (Math.abs((int) event.getX() - mDragStartX) < slop
                    && Math.abs((int) event.getY() - mDragStartY) < slop) {
                // If the user has not scrolled further than slop, we should not
                // send the drag.  Instead, do nothing, and when the user lifts
                // their finger, we will change the selection.
                return true;
            }
            if (mWebView != null) {
                // Only want to set the initial state once.
                if (!mDragSent) {
                    mWebView.initiateTextFieldDrag(mDragStartX, mDragStartY,
                            mDragStartTime);
                    mDragSent = true;
                }
                boolean scrolled = mWebView.textFieldDrag(event);
                if (scrolled) {
                    mScrolled = true;
                    cancelLongPress();
                    return true;
                }
            }
            return false;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            super.onTouchEvent(event);
            if (mHasPerformedLongClick) {
                mGotTouchDown = false;
                return false;
            }
            if (!mScrolled) {
                // If the page scrolled, or the TextView scrolled, we do not
                // want to change the selection
                cancelLongPress();
                if (mGotTouchDown && mWebView != null) {
                    mWebView.touchUpOnTextField(event);
                }
            }
            // Necessary for the WebView to reset its state
            if (mWebView != null && mDragSent) {
                mWebView.onTouchEvent(event);
            }
            mGotTouchDown = false;
            break;
        default:
            break;
        }
        return true;
    }

    @Override
    public boolean onTrackballEvent(MotionEvent event) {
        if (isPopupShowing()) {
            return super.onTrackballEvent(event);
        }
        if (event.getAction() != MotionEvent.ACTION_MOVE) {
            return false;
        }
        Spannable text = getText();
        MovementMethod move = getMovementMethod();
        if (move != null && getLayout() != null &&
            move.onTrackballEvent(this, text, event)) {
            // Selection is changed in onSelectionChanged
            return true;
        }
        return false;
    }

    @Override
    public boolean performLongClick() {
        mHasPerformedLongClick = true;
        return super.performLongClick();
    }

    /**
     * Remove this WebTextView from its host WebView, and return
     * focus to the host.
     */
    /* package */ void remove() {
        // hide the soft keyboard when the edit text is out of focus
        InputMethodManager imm = InputMethodManager.getInstance(mContext);
        if (imm.isActive(this)) {
            imm.hideSoftInputFromWindow(getWindowToken(), 0);
        }
        mInsideRemove = true;
        mWebView.removeView(this);
        mWebView.requestFocus();
        mInsideRemove = false;
    }

    @Override
    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
        // Do nothing, since webkit will put the textfield on screen.
        return true;
    }

    /**
     *  Send the DOM events for the specified event.
     *  @param event    KeyEvent to be translated into a DOM event.
     */
    private void sendDomEvent(KeyEvent event) {
        mWebView.passToJavaScript(getText().toString(), event);
    }

    /**
     *  Always use this instead of setAdapter, as this has features specific to
     *  the WebTextView.
     */
    public void setAdapterCustom(AutoCompleteAdapter adapter) {
        if (adapter != null) {
            setInputType(getInputType()
                    | EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE);
            adapter.setTextView(this);
            if (mAutoFillable) {
                setOnItemClickListener(this);
            } else {
                setOnItemClickListener(null);
            }
            showDropDown();
        } else {
            dismissDropDown();
        }
        super.setAdapter(adapter);
    }

    /**
     *  This is a special version of ArrayAdapter which changes its text size
     *  to match the text size of its host TextView.
     */
    public static class AutoCompleteAdapter extends ArrayAdapter<String> {
        private TextView mTextView;

        public AutoCompleteAdapter(Context context, ArrayList<String> entries) {
            super(context, com.android.internal.R.layout
                    .web_text_view_dropdown, entries);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView tv =
                    (TextView) super.getView(position, convertView, parent);
            if (tv != null && mTextView != null) {
                tv.setTextSize(mTextView.getTextSize());
            }
            return tv;
        }

        /**
         * Set the TextView so we can match its text size.
         */
        private void setTextView(TextView tv) {
            mTextView = tv;
        }
    }

    /**
     * Sets the selection when the user clicks on a textfield or textarea with
     * the trackball or center key, or starts typing into it without clicking on
     * it.
     */
    /* package */ void setDefaultSelection() {
        Spannable text = (Spannable) getText();
        int selection = mSingle ? text.length() : 0;
        if (Selection.getSelectionStart(text) == selection
                && Selection.getSelectionEnd(text) == selection) {
            // The selection of the UI copy is set correctly, but the
            // WebTextView still needs to inform the webkit thread to set the
            // selection.  Normally that is done in onSelectionChanged, but
            // onSelectionChanged will not be called because the UI copy is not
            // changing.  (This can happen when the WebTextView takes focus.
            // That onSelectionChanged was blocked because the selection set
            // when focusing is not necessarily the desirable selection for
            // WebTextView.)
            if (mWebView != null) {
                mWebView.setSelection(selection, selection);
            }
        } else {
            Selection.setSelection(text, selection, selection);
        }
        if (mWebView != null) mWebView.incrementTextGeneration();
    }

    /**
     * Determine whether to use the system-wide password disguising method,
     * or to use none.
     * @param   inPassword  True if the textfield is a password field.
     */
    /* package */ void setInPassword(boolean inPassword) {
        if (inPassword) {
            setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.
                TYPE_TEXT_VARIATION_WEB_PASSWORD);
            createBackground();
        }
        // For password fields, draw the WebTextView.  For others, just show
        // webkit's drawing.
        if (!DebugFlags.DRAW_WEBTEXTVIEW) {
            setWillNotDraw(!inPassword);
        }
        setBackgroundDrawable(inPassword ? mBackground : null);
    }

    /**
     * Private class used for the background of a password textfield.
     */
    private static class OutlineDrawable extends Drawable {
        private Paint mBackgroundPaint;
        private Paint mOutlinePaint;
        private float[] mLines;
        public OutlineDrawable() {
            mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mBackgroundPaint.setColor(Color.WHITE);

            mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mOutlinePaint.setColor(Color.BLACK);
            mOutlinePaint.setStyle(Paint.Style.STROKE);

            mLines = new float[16];
        }
        @Override
        public void setBounds(int left, int top, int right, int bottom) {
            super.setBounds(left, top, right, bottom);
            bottom--;
            right -= 2;
            // Top line
            mLines[0] = left;
            mLines[1] = top + 1;
            mLines[2] = right;
            mLines[3] = top + 1;
            // Right line
            mLines[4] = right;
            mLines[5] = top;
            mLines[6] = right;
            mLines[7] = bottom;
            // Bottom line
            mLines[8] = left;
            mLines[9] = bottom;
            mLines[10] = right;
            mLines[11] = bottom;
            // Left line
            mLines[12] = left + 1;
            mLines[13] = top;
            mLines[14] = left + 1;
            mLines[15] = bottom;
        }
        @Override
        public void draw(Canvas canvas) {
            // Draw the background.
            canvas.drawRect(getBounds(), mBackgroundPaint);
            // Draw the outline.
            canvas.drawLines(mLines, mOutlinePaint);
        }
        // Always want it to be opaque.
        @Override
        public int getOpacity() {
            return PixelFormat.OPAQUE;
        }
        // These are needed because they are abstract in Drawable.
        @Override
        public void setAlpha(int alpha) { }
        @Override
        public void setColorFilter(ColorFilter cf) { }
    }

    /**
     * Create a background for the WebTextView and set up the paint for drawing
     * the text.  This way, we can see the password transformation of the
     * system, which (optionally) shows the actual text before changing to dots.
     * The background is necessary to hide the webkit-drawn text beneath.
     */
    private void createBackground() {
        if (mBackground != null) {
            return;
        }
        mBackground = new OutlineDrawable();

        setGravity(Gravity.CENTER_VERTICAL);
    }

    @Override
    public void setInputType(int type) {
        mFromSetInputType = true;
        super.setInputType(type);
        mFromSetInputType = false;
    }

    private void setMaxLength(int maxLength) {
        mMaxLength = maxLength;
        if (-1 == maxLength) {
            setFilters(NO_FILTERS);
        } else {
            setFilters(new InputFilter[] {
                new InputFilter.LengthFilter(maxLength) });
        }
    }

    /**
     *  Set the pointer for this node so it can be determined which node this
     *  WebTextView represents.
     *  @param  ptr Integer representing the pointer to the node which this
     *          WebTextView represents.
     */
    /* package */ void setNodePointer(int ptr) {
        mNodePointer = ptr;
    }

    /**
     * Determine the position and size of WebTextView, and add it to the
     * WebView's view heirarchy.  All parameters are presumed to be in
     * view coordinates.  Also requests Focus and sets the cursor to not
     * request to be in view.
     * @param x         x-position of the textfield.
     * @param y         y-position of the textfield.
     * @param width     width of the textfield.
     * @param height    height of the textfield.
     */
    /* package */ void setRect(int x, int y, int width, int height) {
        LayoutParams lp = (LayoutParams) getLayoutParams();
        if (null == lp) {
            lp = new LayoutParams(width, height, x, y);
        } else {
            lp.x = x;
            lp.y = y;
            lp.width = width;
            lp.height = height;
        }
        if (getParent() == null) {
            mWebView.addView(this, lp);
        } else {
            setLayoutParams(lp);
        }
        // Set up a measure spec so a layout can always be recreated.
        mWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
        mHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
    }

    /**
     * Set the selection, and disable our onSelectionChanged action.
     */
    /* package */ void setSelectionFromWebKit(int start, int end) {
        if (start < 0 || end < 0) return;
        Spannable text = (Spannable) getText();
        int length = text.length();
        if (start > length || end > length) return;
        mFromWebKit = true;
        Selection.setSelection(text, start, end);
        mFromWebKit = false;
    }

    /**
     * Update the text size according to the size of the focus candidate's text
     * size in mWebView.  Should only be called from mWebView.
     */
    /* package */ void updateTextSize() {
        Assert.assertNotNull("updateTextSize should only be called from "
                + "mWebView, so mWebView should never be null!", mWebView);
        // Note that this is approximately WebView.contentToViewDimension,
        // without being rounded.
        float size = mWebView.nativeFocusCandidateTextSize()
                * mWebView.getScale();
        setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
    }

    /**
     * Set the text to the new string, but use the old selection, making sure
     * to keep it within the new string.
     * @param   text    The new text to place in the textfield.
     */
    /* package */ void setTextAndKeepSelection(String text) {
        mPreChange = text.toString();
        Editable edit = getText();
        int selStart = Selection.getSelectionStart(edit);
        int selEnd = Selection.getSelectionEnd(edit);
        mInSetTextAndKeepSelection = true;
        edit.replace(0, edit.length(), text);
        int newLength = edit.length();
        if (selStart > newLength) selStart = newLength;
        if (selEnd > newLength) selEnd = newLength;
        Selection.setSelection(edit, selStart, selEnd);
        mInSetTextAndKeepSelection = false;
        InputMethodManager imm = InputMethodManager.peekInstance();
        if (imm != null && imm.isActive(this)) {
            // Since the text has changed, do not allow the IME to replace the
            // existing text as though it were a completion.
            imm.restartInput(this);
        }
        updateCachedTextfield();
    }

    /**
     * Called by WebView.rebuildWebTextView().  Based on the type of the <input>
     * element, set up the WebTextView, its InputType, and IME Options properly.
     * @param type int corresponding to enum "Type" defined in CachedInput.h.
     *              Does not correspond to HTMLInputElement::InputType so this
     *              is unaffected if that changes, and also because that has no
     *              type corresponding to textarea (which is its own tag).
     */
    /* package */ void setType(int type) {
        if (mWebView == null) return;
        boolean single = true;
        boolean inPassword = false;
        int maxLength = -1;
        int inputType = EditorInfo.TYPE_CLASS_TEXT
                | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
        int imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
                | EditorInfo.IME_FLAG_NO_FULLSCREEN;
        if (TEXT_AREA != type
                && mWebView.nativeFocusCandidateHasNextTextfield()) {
            imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
        }
        switch (type) {
            case NORMAL_TEXT_FIELD:
                imeOptions |= EditorInfo.IME_ACTION_GO;
                break;
            case TEXT_AREA:
                single = false;
                inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
                        | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
                        | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
                imeOptions |= EditorInfo.IME_ACTION_NONE;
                break;
            case PASSWORD:
                inPassword = true;
                imeOptions |= EditorInfo.IME_ACTION_GO;
                break;
            case SEARCH:
                imeOptions |= EditorInfo.IME_ACTION_SEARCH;
                break;
            case EMAIL:
                inputType = EditorInfo.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
                imeOptions |= EditorInfo.IME_ACTION_GO;
                break;
            case NUMBER:
                inputType |= EditorInfo.TYPE_CLASS_NUMBER;
                // Number and telephone do not have both a Tab key and an
                // action, so set the action to NEXT
                imeOptions |= EditorInfo.IME_ACTION_NEXT;
                break;
            case TELEPHONE:
                inputType |= EditorInfo.TYPE_CLASS_PHONE;
                imeOptions |= EditorInfo.IME_ACTION_NEXT;
                break;
            case URL:
                // TYPE_TEXT_VARIATION_URI prevents Tab key from showing, so
                // exclude it for now.
                imeOptions |= EditorInfo.IME_ACTION_GO;
                break;
            default:
                imeOptions |= EditorInfo.IME_ACTION_GO;
                break;
        }
        setHint(null);
        if (single) {
            mWebView.requestLabel(mWebView.nativeFocusCandidateFramePointer(),
                    mNodePointer);
            maxLength = mWebView.nativeFocusCandidateMaxLength();
            boolean autoComplete = mWebView.nativeFocusCandidateIsAutoComplete();
            if (type != PASSWORD && (mAutoFillable || autoComplete)) {
                String name = mWebView.nativeFocusCandidateName();
                if (name != null && name.length() > 0) {
                    mWebView.requestFormData(name, mNodePointer, mAutoFillable,
                            autoComplete);
                }
            }
        }
        mSingle = single;
        setMaxLength(maxLength);
        setHorizontallyScrolling(single);
        setInputType(inputType);
        setImeOptions(imeOptions);
        setInPassword(inPassword);
        AutoCompleteAdapter adapter = null;
        setAdapterCustom(adapter);
    }

    /**
     *  Update the cache to reflect the current text.
     */
    /* package */ void updateCachedTextfield() {
        mWebView.updateCachedTextfield(getText().toString());
    }

    /* package */ void setAutoFillProfileIsSet(boolean autoFillProfileIsSet) {
        mAutoFillProfileIsSet = autoFillProfileIsSet;
    }
}
