/*
 * 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.inputmethodservice;

import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
import android.window.WindowProviderService;

import com.android.internal.annotations.VisibleForTesting;

import java.io.FileDescriptor;
import java.io.PrintWriter;

/**
 * AbstractInputMethodService provides a abstract base class for input methods.
 * Normal input method implementations will not derive from this directly,
 * instead building on top of {@link InputMethodService} or another more
 * complete base class.  Be sure to read {@link InputMethod} for more
 * information on the basics of writing input methods.
 * 
 * <p>This class combines a Service (representing the input method component
 * to the system with the InputMethod interface that input methods must
 * implement.  This base class takes care of reporting your InputMethod from
 * the service when clients bind to it, but provides no standard implementation
 * of the InputMethod interface itself.  Derived classes must implement that
 * interface.</p>
 *
 * <p>After {@link android.os.Build.VERSION_CODES#S}, the maximum possible area to show the soft
 * input may not be the entire screen. For example, some devices may support to show the soft input
 * on only half of screen.</p>
 *
 * <p>In that case, moving the soft input from one half screen to another will trigger a
 * {@link android.content.res.Resources} update to match the new {@link Configuration} and
 * this {@link AbstractInputMethodService} may also receive a
 * {@link #onConfigurationChanged(Configuration)} callback if there's notable configuration changes
 * </p>
 *
 * @see android.content.ComponentCallbacks#onConfigurationChanged(Configuration)
 * @see Context#isUiContext Context#isUiContext to see the concept of UI Context.
 */
public abstract class AbstractInputMethodService extends WindowProviderService
        implements KeyEvent.Callback {
    private InputMethod mInputMethod;

    /**
     * @return {@link InputMethod} instance returned from {@link #onCreateInputMethodInterface()}.
     *         {@code null} if {@link #onCreateInputMethodInterface()} is not yet called.
     * @hide
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    @Nullable
    public final InputMethod getInputMethodInternal() {
        return mInputMethod;
    }

    /**
     * Keep the strong reference to {@link InputMethodServiceInternal} to ensure that it will not be
     * garbage-collected until {@link AbstractInputMethodService} gets garbage-collected.
     *
     * <p>This is necessary because {@link RemoteInputConnection} internally uses
     * {@link java.lang.ref.WeakReference} to hold {@link InputMethodServiceInternal}.</p>
     */
    @Nullable
    private InputMethodServiceInternal mInputMethodServiceInternal;

    final KeyEvent.DispatcherState mDispatcherState
            = new KeyEvent.DispatcherState();

    /**
     * Base class for derived classes to implement their {@link InputMethod}
     * interface.  This takes care of basic maintenance of the input method,
     * but most behavior must be implemented in a derived class.
     */
    public abstract class AbstractInputMethodImpl implements InputMethod {
        /**
         * Instantiate a new client session for the input method, by calling
         * back to {@link AbstractInputMethodService#onCreateInputMethodSessionInterface()
         * AbstractInputMethodService.onCreateInputMethodSessionInterface()}.
         */
        @MainThread
        public void createSession(SessionCallback callback) {
            callback.sessionCreated(onCreateInputMethodSessionInterface());
        }
        
        /**
         * Take care of enabling or disabling an existing session by calling its
         * {@link AbstractInputMethodSessionImpl#revokeSelf()
         * AbstractInputMethodSessionImpl.setEnabled()} method.
         */
        @MainThread
        public void setSessionEnabled(InputMethodSession session, boolean enabled) {
            ((AbstractInputMethodSessionImpl)session).setEnabled(enabled);
        }
        
        /**
         * Take care of killing an existing session by calling its
         * {@link AbstractInputMethodSessionImpl#revokeSelf()
         * AbstractInputMethodSessionImpl.revokeSelf()} method.
         */
        @MainThread
        public void revokeSession(InputMethodSession session) {
            ((AbstractInputMethodSessionImpl)session).revokeSelf();
        }
    }
    
    /**
     * Base class for derived classes to implement their {@link InputMethodSession}
     * interface.  This takes care of basic maintenance of the session,
     * but most behavior must be implemented in a derived class.
     */
    public abstract class AbstractInputMethodSessionImpl implements InputMethodSession {
        boolean mEnabled = true;
        boolean mRevoked;
        
        /**
         * Check whether this session has been enabled by the system.  If not
         * enabled, you should not execute any calls on to it.
         */
        public boolean isEnabled() {
            return mEnabled;
        }
        
        /**
         * Check whether this session has been revoked by the system.  Revoked
         * session is also always disabled, so there is generally no need to
         * explicitly check for this.
         */
        public boolean isRevoked() {
            return mRevoked;
        }
        
        /**
         * Change the enabled state of the session.  This only works if the
         * session has not been revoked.
         */
        public void setEnabled(boolean enabled) {
            if (!mRevoked) {
                mEnabled = enabled;
            }
        }
        
        /**
         * Revoke the session from the client.  This disabled the session, and
         * prevents it from ever being enabled again.
         */
        public void revokeSelf() {
            mRevoked = true;
            mEnabled = false;
        }

        /**
         * Take care of dispatching incoming key events to the appropriate
         * callbacks on the service, and tell the client when this is done.
         */
        @Override
        public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback) {
            boolean handled = event.dispatch(AbstractInputMethodService.this,
                    mDispatcherState, this);
            if (callback != null) {
                callback.finishedEvent(seq, handled);
            }
        }

        /**
         * Take care of dispatching incoming trackball events to the appropriate
         * callbacks on the service, and tell the client when this is done.
         */
        @Override
        public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback) {
            boolean handled = onTrackballEvent(event);
            if (callback != null) {
                callback.finishedEvent(seq, handled);
            }
        }

        /**
         * Take care of dispatching incoming generic motion events to the appropriate
         * callbacks on the service, and tell the client when this is done.
         */
        @Override
        public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback) {
            boolean handled = onGenericMotionEvent(event);
            if (callback != null) {
                callback.finishedEvent(seq, handled);
            }
        }
    }
    
    /**
     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
     * for used for processing events from the target application.
     * Normally you will not need to use this directly, but
     * just use the standard high-level event callbacks like {@link #onKeyDown}.
     */
    public KeyEvent.DispatcherState getKeyDispatcherState() {
        return mDispatcherState;
    }
    
    /**
     * Called by the framework during initialization, when the InputMethod
     * interface for this service needs to be created.
     */
    public abstract AbstractInputMethodImpl onCreateInputMethodInterface();
    
    /**
     * Called by the framework when a new InputMethodSession interface is
     * needed for a new client of the input method.
     */
    public abstract AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();

    /**
     * Implement this to handle {@link android.os.Binder#dump Binder.dump()}
     * calls on your input method.
     */
    @Override
    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
    }

    @Override
    final public IBinder onBind(Intent intent) {
        if (mInputMethod == null) {
            mInputMethod = onCreateInputMethodInterface();
        }
        if (mInputMethodServiceInternal == null) {
            mInputMethodServiceInternal = createInputMethodServiceInternal();
        }
        return new IInputMethodWrapper(mInputMethodServiceInternal, mInputMethod);
    }

    /**
     * Used to inject custom {@link InputMethodServiceInternal}.
     *
     * @return the {@link InputMethodServiceInternal} to be used.
     */
    @NonNull
    InputMethodServiceInternal createInputMethodServiceInternal() {
        return new InputMethodServiceInternal() {
            /**
             * {@inheritDoc}
             */
            @NonNull
            @Override
            public Context getContext() {
                return AbstractInputMethodService.this;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
                AbstractInputMethodService.this.dump(fd, fout, args);
            }
        };
    }

    /**
     * Implement this to handle trackball events on your input method.
     *
     * @param event The motion event being received.
     * @return True if the event was handled in this function, false otherwise.
     * @see android.view.View#onTrackballEvent(MotionEvent)
     */
    public boolean onTrackballEvent(MotionEvent event) {
        return false;
    }

    /**
     * Implement this to handle generic motion events on your input method.
     *
     * @param event The motion event being received.
     * @return True if the event was handled in this function, false otherwise.
     * @see android.view.View#onGenericMotionEvent(MotionEvent)
     */
    public boolean onGenericMotionEvent(MotionEvent event) {
        return false;
    }

    /** @hide */
    @Override
    public final int getWindowType() {
        return WindowManager.LayoutParams.TYPE_INPUT_METHOD;
    }

    /** @hide */
    @Override
    @Nullable
    public final Bundle getWindowContextOptions() {
        return super.getWindowContextOptions();
    }

    /** @hide */
    @Override
    public final int getInitialDisplayId() {
        try {
            return WindowManagerGlobal.getWindowManagerService().getImeDisplayId();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
