/*
 * Copyright (C) 2018 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.appprediction;

import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.CallSuper;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Service;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionSessionId;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
import android.app.prediction.AppTargetId;
import android.app.prediction.IPredictionCallback;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.service.appprediction.IPredictionService.Stub;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * A service used to predict app and shortcut usage.
 *
 * @hide
 */
@SystemApi
@TestApi
public abstract class AppPredictionService extends Service {

    private static final String TAG = "AppPredictionService";

    /**
     * The {@link Intent} that must be declared as handled by the service.
     *
     * <p>The service must also require the {@link android.permission#MANAGE_APP_PREDICTIONS}
     * permission.
     *
     * @hide
     */
    public static final String SERVICE_INTERFACE =
            "android.service.appprediction.AppPredictionService";

    private final ArrayMap<AppPredictionSessionId, ArrayList<CallbackWrapper>> mSessionCallbacks =
            new ArrayMap<>();
    private Handler mHandler;

    private final IPredictionService mInterface = new Stub() {

        @Override
        public void onCreatePredictionSession(AppPredictionContext context,
                AppPredictionSessionId sessionId) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::doCreatePredictionSession,
                            AppPredictionService.this, context, sessionId));
        }

        @Override
        public void notifyAppTargetEvent(AppPredictionSessionId sessionId, AppTargetEvent event) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::onAppTargetEvent,
                            AppPredictionService.this, sessionId, event));
        }

        @Override
        public void notifyLaunchLocationShown(AppPredictionSessionId sessionId,
                String launchLocation, ParceledListSlice targetIds) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::onLaunchLocationShown,
                            AppPredictionService.this, sessionId, launchLocation,
                            targetIds.getList()));
        }

        @Override
        public void sortAppTargets(AppPredictionSessionId sessionId, ParceledListSlice targets,
                IPredictionCallback callback) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::onSortAppTargets,
                            AppPredictionService.this, sessionId, targets.getList(), null,
                            new CallbackWrapper(callback, null)));
        }

        @Override
        public void registerPredictionUpdates(AppPredictionSessionId sessionId,
                IPredictionCallback callback) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::doRegisterPredictionUpdates,
                            AppPredictionService.this, sessionId, callback));
        }

        @Override
        public void unregisterPredictionUpdates(AppPredictionSessionId sessionId,
                IPredictionCallback callback) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::doUnregisterPredictionUpdates,
                            AppPredictionService.this, sessionId, callback));
        }

        @Override
        public void requestPredictionUpdate(AppPredictionSessionId sessionId) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::doRequestPredictionUpdate,
                            AppPredictionService.this, sessionId));
        }

        @Override
        public void onDestroyPredictionSession(AppPredictionSessionId sessionId) {
            mHandler.sendMessage(
                    obtainMessage(AppPredictionService::doDestroyPredictionSession,
                            AppPredictionService.this, sessionId));
        }
    };

    @CallSuper
    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler(Looper.getMainLooper(), null, true);
    }

    @Override
    @NonNull
    public final IBinder onBind(@NonNull Intent intent) {
        if (SERVICE_INTERFACE.equals(intent.getAction())) {
            return mInterface.asBinder();
        }
        Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
        return null;
    }

    /**
     * Called by a client app to indicate a target launch
     */
    @MainThread
    public abstract void onAppTargetEvent(@NonNull AppPredictionSessionId sessionId,
            @NonNull AppTargetEvent event);

    /**
     * Called by a client app to indication a particular location has been shown to the user.
     */
    @MainThread
    public abstract void onLaunchLocationShown(@NonNull AppPredictionSessionId sessionId,
            @NonNull String launchLocation, @NonNull List<AppTargetId> targetIds);

    private void doCreatePredictionSession(@NonNull AppPredictionContext context,
            @NonNull AppPredictionSessionId sessionId) {
        mSessionCallbacks.put(sessionId, new ArrayList<>());
        onCreatePredictionSession(context, sessionId);
    }

    /**
     * Creates a new interaction session.
     *
     * @param context interaction context
     * @param sessionId the session's Id
     */
    public void onCreatePredictionSession(@NonNull AppPredictionContext context,
            @NonNull AppPredictionSessionId sessionId) {}

    /**
     * Called by the client app to request sorting of targets based on prediction rank.
     */
    @MainThread
    public abstract void onSortAppTargets(@NonNull AppPredictionSessionId sessionId,
            @NonNull List<AppTarget> targets, @NonNull CancellationSignal cancellationSignal,
            @NonNull Consumer<List<AppTarget>> callback);

    private void doRegisterPredictionUpdates(@NonNull AppPredictionSessionId sessionId,
            @NonNull IPredictionCallback callback) {
        final ArrayList<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId);
        if (callbacks == null) {
            Slog.e(TAG, "Failed to register for updates for unknown session: " + sessionId);
            return;
        }

        final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback);
        if (wrapper == null) {
            callbacks.add(new CallbackWrapper(callback,
                    callbackWrapper ->
                        mHandler.post(() -> removeCallbackWrapper(callbacks, callbackWrapper))));
            if (callbacks.size() == 1) {
                onStartPredictionUpdates();
            }
        }
    }

    /**
     * Called when any continuous prediction callback is registered.
     */
    @MainThread
    public void onStartPredictionUpdates() {}

    private void doUnregisterPredictionUpdates(@NonNull AppPredictionSessionId sessionId,
            @NonNull IPredictionCallback callback) {
        final ArrayList<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId);
        if (callbacks == null) {
            Slog.e(TAG, "Failed to unregister for updates for unknown session: " + sessionId);
            return;
        }

        final CallbackWrapper wrapper = findCallbackWrapper(callbacks, callback);
        if (wrapper != null) {
            removeCallbackWrapper(callbacks, wrapper);
        }
    }

    private void removeCallbackWrapper(
                ArrayList<CallbackWrapper> callbacks, CallbackWrapper wrapper) {
        if (callbacks == null) {
            return;
        }
        callbacks.remove(wrapper);
        if (callbacks.isEmpty()) {
            onStopPredictionUpdates();
        }
    }

    /**
     * Called when there are no longer any continuous prediction callbacks registered.
     */
    @MainThread
    public void onStopPredictionUpdates() {}

    private void doRequestPredictionUpdate(@NonNull AppPredictionSessionId sessionId) {
        // Just an optimization, if there are no callbacks, then don't bother notifying the service
        final ArrayList<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId);
        if (callbacks != null && !callbacks.isEmpty()) {
            onRequestPredictionUpdate(sessionId);
        }
    }

    /**
     * Called by the client app to request target predictions. This method is only called if there
     * are one or more prediction callbacks registered.
     *
     * @see #updatePredictions(AppPredictionSessionId, List)
     */
    @MainThread
    public abstract void onRequestPredictionUpdate(@NonNull AppPredictionSessionId sessionId);

    private void doDestroyPredictionSession(@NonNull AppPredictionSessionId sessionId) {
        mSessionCallbacks.remove(sessionId);
        onDestroyPredictionSession(sessionId);
    }

    /**
     * Destroys the interaction session.
     *
     * @param sessionId the id of the session to destroy
     */
    @MainThread
    public void onDestroyPredictionSession(@NonNull AppPredictionSessionId sessionId) {}

    /**
     * Used by the prediction factory to send back results the client app. The can be called
     * in response to {@link #onRequestPredictionUpdate(AppPredictionSessionId)} or proactively as
     * a result of changes in predictions.
     */
    public final void updatePredictions(@NonNull AppPredictionSessionId sessionId,
            @NonNull List<AppTarget> targets) {
        List<CallbackWrapper> callbacks = mSessionCallbacks.get(sessionId);
        if (callbacks != null) {
            for (CallbackWrapper callback : callbacks) {
                callback.accept(targets);
            }
        }
    }

    /**
     * Finds the callback wrapper for the given callback.
     */
    private CallbackWrapper findCallbackWrapper(ArrayList<CallbackWrapper> callbacks,
            IPredictionCallback callback) {
        for (int i = callbacks.size() - 1; i >= 0; i--) {
            if (callbacks.get(i).isCallback(callback)) {
                return callbacks.get(i);
            }
        }
        return null;
    }

    private static final class CallbackWrapper implements Consumer<List<AppTarget>>,
            IBinder.DeathRecipient {

        private IPredictionCallback mCallback;
        private final Consumer<CallbackWrapper> mOnBinderDied;

        CallbackWrapper(IPredictionCallback callback,
                @Nullable Consumer<CallbackWrapper> onBinderDied) {
            mCallback = callback;
            mOnBinderDied = onBinderDied;
            try {
                mCallback.asBinder().linkToDeath(this, 0);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to link to death: " + e);
            }
        }

        public boolean isCallback(@NonNull IPredictionCallback callback) {
            if (mCallback == null) {
                Slog.e(TAG, "Callback is null, likely the binder has died.");
                return false;
            }
            return mCallback.equals(callback);
        }

        @Override
        public void accept(List<AppTarget> ts) {
            try {
                if (mCallback != null) {
                    mCallback.onResult(new ParceledListSlice(ts));
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Error sending result:" + e);
            }
        }

        @Override
        public void binderDied() {
            mCallback = null;
            if (mOnBinderDied != null) {
                mOnBinderDied.accept(this);
            }
        }
    }
}
