/*
 * 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>Implementations of this interface should generally be done by
 * subclassing {@link BaseInputConnection}.
 */
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);
}
