/*
 * Copyright (C) 2011 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.service.textservice;

import com.android.internal.textservice.ISpellCheckerService;
import com.android.internal.textservice.ISpellCheckerSession;
import com.android.internal.textservice.ISpellCheckerSessionListener;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;

import java.lang.ref.WeakReference;

/**
 * SpellCheckerService provides an abstract base class for a spell checker.
 * This class combines a service to the system with the spell checker service interface that
 * spell checker must implement.
 *
 * <p>In addition to the normal Service lifecycle methods, this class
 * introduces a new specific callback that subclasses should override
 * {@link #createSession()} to provide a spell checker session that is corresponding
 * to requested language and so on. The spell checker session returned by this method
 * should extend {@link SpellCheckerService.Session}.
 * </p>
 *
 * <h3>Returning spell check results</h3>
 *
 * <p>{@link SpellCheckerService.Session#onGetSuggestions(TextInfo, int)}
 * should return spell check results.
 * It receives {@link android.view.textservice.TextInfo} and returns
 * {@link android.view.textservice.SuggestionsInfo} for the input.
 * You may want to override
 * {@link SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean)} for
 * better performance and quality.
 * </p>
 *
 * <p>Please note that {@link SpellCheckerService.Session#getLocale()} does not return a valid
 * locale before {@link SpellCheckerService.Session#onCreate()} </p>
 *
 */
public abstract class SpellCheckerService extends Service {
    private static final String TAG = SpellCheckerService.class.getSimpleName();
    private static final boolean DBG = false;
    public static final String SERVICE_INTERFACE =
            "android.service.textservice.SpellCheckerService";

    private final SpellCheckerServiceBinder mBinder = new SpellCheckerServiceBinder(this);


    /**
     * Implement to return the implementation of the internal spell checker
     * service interface. Subclasses should not override.
     */
    @Override
    public final IBinder onBind(final Intent intent) {
        if (DBG) {
            Log.w(TAG, "onBind");
        }
        return mBinder;
    }

    /**
     * Factory method to create a spell checker session impl
     * @return SpellCheckerSessionImpl which should be overridden by a concrete implementation.
     */
    public abstract Session createSession();

    /**
     * This abstract class should be overridden by a concrete implementation of a spell checker.
     */
    public static abstract class Session {
        private InternalISpellCheckerSession mInternalSession;

        /**
         * @hide
         */
        public final void setInternalISpellCheckerSession(InternalISpellCheckerSession session) {
            mInternalSession = session;
        }

        /**
         * This is called after the class is initialized, at which point it knows it can call
         * getLocale() etc...
         */
        public abstract void onCreate();

        /**
         * Get suggestions for specified text in TextInfo.
         * This function will run on the incoming IPC thread.
         * So, this is not called on the main thread,
         * but will be called in series on another thread.
         * @param textInfo the text metadata
         * @param suggestionsLimit the number of limit of suggestions returned
         * @return SuggestionsInfo which contains suggestions for textInfo
         */
        public abstract SuggestionsInfo onGetSuggestions(TextInfo textInfo, int suggestionsLimit);

        /**
         * A batch process of onGetSuggestions.
         * This function will run on the incoming IPC thread.
         * So, this is not called on the main thread,
         * but will be called in series on another thread.
         * @param textInfos an array of the text metadata
         * @param suggestionsLimit the number of limit of suggestions returned
         * @param sequentialWords true if textInfos can be treated as sequential words.
         * @return an array of SuggestionsInfo of onGetSuggestions
         */
        public SuggestionsInfo[] onGetSuggestionsMultiple(TextInfo[] textInfos,
                int suggestionsLimit, boolean sequentialWords) {
            final int length = textInfos.length;
            final SuggestionsInfo[] retval = new SuggestionsInfo[length];
            for (int i = 0; i < length; ++i) {
                retval[i] = onGetSuggestions(textInfos[i], suggestionsLimit);
                retval[i].setCookieAndSequence(
                        textInfos[i].getCookie(), textInfos[i].getSequence());
            }
            return retval;
        }

        /**
         * @hide
         * The default implementation returns an array of SuggestionsInfo by simply calling
         * onGetSuggestions().
         * When you override this method, make sure that suggestionsLimit is applied to suggestions
         * that share the same start position and length.
         */
        public SuggestionsInfo[] onGetSuggestionsMultipleForSentence(TextInfo[] textInfos,
                int suggestionsLimit) {
            final int length = textInfos.length;
            final SuggestionsInfo[] retval = new SuggestionsInfo[length];
            for (int i = 0; i < length; ++i) {
                retval[i] = onGetSuggestions(textInfos[i], suggestionsLimit);
                retval[i].setCookieAndSequence(
                        textInfos[i].getCookie(), textInfos[i].getSequence());
            }
            return retval;
        }

        /**
         * Request to abort all tasks executed in SpellChecker.
         * This function will run on the incoming IPC thread.
         * So, this is not called on the main thread,
         * but will be called in series on another thread.
         */
        public void onCancel() {}

        /**
         * Request to close this session.
         * This function will run on the incoming IPC thread.
         * So, this is not called on the main thread,
         * but will be called in series on another thread.
         */
        public void onClose() {}

        /**
         * @return Locale for this session
         */
        public String getLocale() {
            return mInternalSession.getLocale();
        }

        /**
         * @return Bundle for this session
         */
        public Bundle getBundle() {
            return mInternalSession.getBundle();
        }
    }

    // Preventing from exposing ISpellCheckerSession.aidl, create an internal class.
    private static class InternalISpellCheckerSession extends ISpellCheckerSession.Stub {
        private ISpellCheckerSessionListener mListener;
        private final Session mSession;
        private final String mLocale;
        private final Bundle mBundle;

        public InternalISpellCheckerSession(String locale, ISpellCheckerSessionListener listener,
                Bundle bundle, Session session) {
            mListener = listener;
            mSession = session;
            mLocale = locale;
            mBundle = bundle;
            session.setInternalISpellCheckerSession(this);
        }

        @Override
        public void onGetSuggestionsMultiple(
                TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
            int pri = Process.getThreadPriority(Process.myTid());
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                mListener.onGetSuggestions(
                        mSession.onGetSuggestionsMultiple(
                                textInfos, suggestionsLimit, sequentialWords));
            } catch (RemoteException e) {
            } finally {
                Process.setThreadPriority(pri);
            }
        }

        @Override
        public void onGetSuggestionsMultipleForSentence(
                TextInfo[] textInfos, int suggestionsLimit) {
            try {
                mListener.onGetSuggestionsForSentence(
                        mSession.onGetSuggestionsMultipleForSentence(textInfos, suggestionsLimit));
            } catch (RemoteException e) {
            }
        }

        @Override
        public void onCancel() {
            int pri = Process.getThreadPriority(Process.myTid());
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                mSession.onCancel();
            } finally {
                Process.setThreadPriority(pri);
            }
        }

        @Override
        public void onClose() {
            int pri = Process.getThreadPriority(Process.myTid());
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                mSession.onClose();
            } finally {
                Process.setThreadPriority(pri);
                mListener = null;
            }
        }

        public String getLocale() {
            return mLocale;
        }

        public Bundle getBundle() {
            return mBundle;
        }
    }

    private static class SpellCheckerServiceBinder extends ISpellCheckerService.Stub {
        private final WeakReference<SpellCheckerService> mInternalServiceRef;

        public SpellCheckerServiceBinder(SpellCheckerService service) {
            mInternalServiceRef = new WeakReference<SpellCheckerService>(service);
        }

        @Override
        public ISpellCheckerSession getISpellCheckerSession(
                String locale, ISpellCheckerSessionListener listener, Bundle bundle) {
            final SpellCheckerService service = mInternalServiceRef.get();
            if (service == null) return null;
            final Session session = service.createSession();
            final InternalISpellCheckerSession internalSession =
                    new InternalISpellCheckerSession(locale, listener, bundle, session);
            session.onCreate();
            return internalSession;
        }
    }
}
