/*
 * Copyright (C) 2007-2008 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.view.inputmethod;

import android.os.Bundle;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;

/**
 * The InputConnection interface is the communication channel from an
 * {@link InputMethod} back to the application that is receiving its input. It
 * is used to perform such things as reading text around the cursor,
 * committing text to the text box, and sending raw key events to the application.
 * 
 * <p>Applications should never directly implement this interface, but instead
 * subclass from {@link BaseInputConnection}.  This will ensure that the
 * application does not break when new methods are added to the interface.
 */
public interface InputConnection {
    /**
     * Flag for use with {@link #getTextAfterCursor} and
     * {@link #getTextBeforeCursor} to have style information returned along
     * with the text.  If not set, you will receive only the raw text.  If
     * set, you may receive a complex CharSequence of both text and style
     * spans.
     */
    static final int GET_TEXT_WITH_STYLES = 0x0001;
    
    /**
     * Flag for use with {@link #getExtractedText} to indicate you would
     * like to receive updates when the extracted text changes.
     */
    public static final int GET_EXTRACTED_TEXT_MONITOR = 0x0001;
    
    /**
     * Get <var>n</var> characters of text before the current cursor position.
     * 
     * <p>This method may fail either if the input connection has become invalid
     * (such as its process crashing) or the client is taking too long to
     * respond with the text (it is given a couple seconds to return).
     * In either case, a null is returned.
     * 
     * @param n The expected length of the text.
     * @param flags Supplies additional options controlling how the text is
     * returned.  May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
     * 
     * @return Returns the text before the cursor position; the length of the
     * returned text might be less than <var>n</var>.
     */
    public CharSequence getTextBeforeCursor(int n, int flags);

    /**
     * Get <var>n</var> characters of text after the current cursor position.
     * 
     * <p>This method may fail either if the input connection has become invalid
     * (such as its process crashing) or the client is taking too long to
     * respond with the text (it is given a couple seconds to return).
     * In either case, a null is returned.
     * 
     * @param n The expected length of the text.
     * @param flags Supplies additional options controlling how the text is
     * returned.  May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
     * 
     * @return Returns the text after the cursor position; the length of the
     * returned text might be less than <var>n</var>.
     */
    public CharSequence getTextAfterCursor(int n, int flags);

    /**
     * Gets the selected text, if any.
     *
     * <p>This method may fail if either the input connection has become
     * invalid (such as its process crashing) or the client is taking too
     * long to respond with the text (it is given a couple of seconds to return).
     * In either case, a null is returned.
     *
     * @param flags Supplies additional options controlling how the text is
     * returned.  May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
     * @return Returns the text that is currently selected, if any, or null if
     * no text is selected.
     */
    public CharSequence getSelectedText(int flags);

    /**
     * Retrieve the current capitalization mode in effect at the current
     * cursor position in the text.  See
     * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode} for
     * more information.
     * 
     * <p>This method may fail either if the input connection has become invalid
     * (such as its process crashing) or the client is taking too long to
     * respond with the text (it is given a couple seconds to return).
     * In either case, a 0 is returned.
     * 
     * @param reqModes The desired modes to retrieve, as defined by
     * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}.  These
     * constants are defined so that you can simply pass the current
     * {@link EditorInfo#inputType TextBoxAttribute.contentType} value
     * directly in to here.
     * 
     * @return Returns the caps mode flags that are in effect.
     */
    public int getCursorCapsMode(int reqModes);
    
    /**
     * Retrieve the current text in the input connection's editor, and monitor
     * for any changes to it.  This function returns with the current text,
     * and optionally the input connection can send updates to the
     * input method when its text changes.
     * 
     * <p>This method may fail either if the input connection has become invalid
     * (such as its process crashing) or the client is taking too long to
     * respond with the text (it is given a couple seconds to return).
     * In either case, a null is returned.
     * 
     * @param request Description of how the text should be returned.
     * @param flags Additional options to control the client, either 0 or
     * {@link #GET_EXTRACTED_TEXT_MONITOR}.
     * 
     * @return Returns an ExtractedText object describing the state of the
     * text view and containing the extracted text itself.
     */
    public ExtractedText getExtractedText(ExtractedTextRequest request,
            int flags);

    /**
     * Delete <var>leftLength</var> characters of text before the current cursor
     * position, and delete <var>rightLength</var> characters of text after the
     * current cursor position, excluding composing text.
     * 
     * @param leftLength The number of characters to be deleted before the
     *        current cursor position.
     * @param rightLength The number of characters to be deleted after the
     *        current cursor position.
     *        
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean deleteSurroundingText(int leftLength, int rightLength);

    /**
     * Set composing text around the current cursor position with the given text,
     * and set the new cursor position.  Any composing text set previously will
     * be removed automatically.
     * 
     * @param text The composing text with styles if necessary. If no style
     *        object attached to the text, the default style for composing text
     *        is used. See {#link android.text.Spanned} for how to attach style
     *        object to the text. {#link android.text.SpannableString} and
     *        {#link android.text.SpannableStringBuilder} are two
     *        implementations of the interface {#link android.text.Spanned}.
     * @param newCursorPosition The new cursor position around the text.  If
     *        > 0, this is relative to the end of the text - 1; if <= 0, this
     *        is relative to the start of the text.  So a value of 1 will
     *        always advance you to the position after the full text being
     *        inserted.  Note that this means you can't position the cursor
     *        within the text, because the editor can make modifications to
     *        the text you are providing so it is not possible to correctly
     *        specify locations there.
     * 
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean setComposingText(CharSequence text, int newCursorPosition);

    /**
     * Mark a certain region of text as composing text. Any composing text set
     * previously will be removed automatically. The default style for composing
     * text is used.
     *
     * @param start the position in the text at which the composing region begins
     * @param end the position in the text at which the composing region ends
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean setComposingRegion(int start, int end);

    /**
     * Have the text editor finish whatever composing text is currently
     * active.  This simply leaves the text as-is, removing any special
     * composing styling or other state that was around it.  The cursor
     * position remains unchanged.
     */
    public boolean finishComposingText();
    
    /**
     * Commit text to the text box and set the new cursor position.
     * Any composing text set previously will be removed
     * automatically.
     * 
     * @param text The committed text.
     * @param newCursorPosition The new cursor position around the text.  If
     *        > 0, this is relative to the end of the text - 1; if <= 0, this
     *        is relative to the start of the text.  So a value of 1 will
     *        always advance you to the position after the full text being
     *        inserted.  Note that this means you can't position the cursor
     *        within the text, because the editor can make modifications to
     *        the text you are providing so it is not possible to correctly
     *        specify locations there.
     * 
     *        
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean commitText(CharSequence text, int newCursorPosition);

    /**
     * Commit a completion the user has selected from the possible ones
     * previously reported to {@link InputMethodSession#displayCompletions
     * InputMethodSession.displayCompletions()}.  This will result in the
     * same behavior as if the user had selected the completion from the
     * actual UI.
     * 
     * @param text The committed completion.
     *        
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean commitCompletion(CompletionInfo text);

    /**
     * Commit a correction automatically performed on the raw user's input. A typical example would
     * be to correct typos using a dictionary.
     *
     * @param correctionInfo Detailed information about the correction.
     *
     * @return True on success, false if the input connection is no longer valid.
     */
    public boolean commitCorrection(CorrectionInfo correctionInfo);

    /**
     * Set the selection of the text editor.  To set the cursor position,
     * start and end should have the same value.
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean setSelection(int start, int end);
    
    /**
     * Have the editor perform an action it has said it can do.
     * 
     * @param editorAction This must be one of the action constants for
     * {@link EditorInfo#imeOptions EditorInfo.editorType}, such as
     * {@link EditorInfo#IME_ACTION_GO EditorInfo.EDITOR_ACTION_GO}.
     * 
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean performEditorAction(int editorAction);
    
    /**
     * Perform a context menu action on the field.  The given id may be one of:
     * {@link android.R.id#selectAll},
     * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
     * {@link android.R.id#cut}, {@link android.R.id#copy},
     * {@link android.R.id#paste}, {@link android.R.id#copyUrl},
     * or {@link android.R.id#switchInputMethod}
     */
    public boolean performContextMenuAction(int id);
    
    /**
     * Tell the editor that you are starting a batch of editor operations.
     * The editor will try to avoid sending you updates about its state
     * until {@link #endBatchEdit} is called.
     */
    public boolean beginBatchEdit();
    
    /**
     * Tell the editor that you are done with a batch edit previously
     * initiated with {@link #endBatchEdit}.
     */
    public boolean endBatchEdit();
    
    /**
     * Send a key event to the process that is currently attached through
     * this input connection.  The event will be dispatched like a normal
     * key event, to the currently focused; this generally is the view that
     * is providing this InputConnection, but due to the asynchronous nature
     * of this protocol that can not be guaranteed and the focus may have
     * changed by the time the event is received.
     * 
     * <p>
     * This method can be used to send key events to the application. For
     * example, an on-screen keyboard may use this method to simulate a hardware
     * keyboard. There are three types of standard keyboards, numeric (12-key),
     * predictive (20-key) and ALPHA (QWERTY). You can specify the keyboard type
     * by specify the device id of the key event.
     * 
     * <p>
     * You will usually want to set the flag
     * {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD} on all
     * key event objects you give to this API; the flag will not be set
     * for you.
     * 
     * @param event The key event.
     *        
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     * 
     * @see KeyEvent
     * @see KeyCharacterMap#NUMERIC
     * @see KeyCharacterMap#PREDICTIVE
     * @see KeyCharacterMap#ALPHA
     */
    public boolean sendKeyEvent(KeyEvent event);

    /**
     * Clear the given meta key pressed states in the given input connection.
     * 
     * @param states The states to be cleared, may be one or more bits as
     * per {@link KeyEvent#getMetaState() KeyEvent.getMetaState()}.
     * 
     * @return Returns true on success, false if the input connection is no longer
     * valid.
     */
    public boolean clearMetaKeyStates(int states);
    
    /**
     * Called by the IME to tell the client when it switches between fullscreen
     * and normal modes.  This will normally be called for you by the standard
     * implementation of {@link android.inputmethodservice.InputMethodService}.
     */
    public boolean reportFullscreenMode(boolean enabled);
    
    /**
     * API to send private commands from an input method to its connected
     * editor.  This can be used to provide domain-specific features that are
     * only known between certain input methods and their clients.  Note that
     * because the InputConnection protocol is asynchronous, you have no way
     * to get a result back or know if the client understood the command; you
     * can use the information in {@link EditorInfo} to determine if
     * a client supports a particular command.
     * 
     * @param action Name of the command to be performed.  This <em>must</em>
     * be a scoped name, i.e. prefixed with a package name you own, so that
     * different developers will not create conflicting commands.
     * @param data Any data to include with the command.
     * @return Returns true if the command was sent (whether or not the
     * associated editor understood it), false if the input connection is no longer
     * valid.
     */
    public boolean performPrivateCommand(String action, Bundle data);
}
