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

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.prediction.IPredictionCallback.Stub;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.Log;

import dalvik.system.CloseGuard;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

/**
 * Class that represents an App Prediction client.
 *
 * <p>
 * Usage: <pre> {@code
 *
 * class MyActivity {
 *    private AppPredictor mClient
 *
 *    void onCreate() {
 *         mClient = new AppPredictor(...)
 *         mClient.registerPredictionUpdates(...)
 *    }
 *
 *    void onStart() {
 *        mClient.requestPredictionUpdate()
 *    }
 *
 *    void onClick(...) {
 *        mClient.notifyAppTargetEvent(...)
 *    }
 *
 *    void onDestroy() {
 *        mClient.unregisterPredictionUpdates()
 *        mClient.close()
 *    }
 *
 * }</pre>
 *
 * @hide
 */
@SystemApi
@TestApi
public final class AppPredictor {

    private static final String TAG = AppPredictor.class.getSimpleName();


    private final IPredictionManager mPredictionManager;
    private final CloseGuard mCloseGuard = CloseGuard.get();
    private final AtomicBoolean mIsClosed = new AtomicBoolean(false);

    private final AppPredictionSessionId mSessionId;
    private final ArrayMap<Callback, CallbackWrapper> mRegisteredCallbacks = new ArrayMap<>();

    /**
     * Creates a new Prediction client.
     * <p>
     * The caller should call {@link AppPredictor#destroy()} to dispose the client once it
     * no longer used.
     *
     * @param context The {@link Context} of the user of this {@link AppPredictor}.
     * @param predictionContext The prediction context.
     */
    AppPredictor(@NonNull Context context, @NonNull AppPredictionContext predictionContext) {
        IBinder b = ServiceManager.getService(Context.APP_PREDICTION_SERVICE);
        mPredictionManager = IPredictionManager.Stub.asInterface(b);
        mSessionId = new AppPredictionSessionId(
                context.getPackageName() + ":" + UUID.randomUUID().toString());
        try {
            mPredictionManager.createPredictionSession(predictionContext, mSessionId);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to create predictor", e);
            e.rethrowAsRuntimeException();
        }

        mCloseGuard.open("close");
    }

    /**
     * Notifies the prediction service of an app target event.
     *
     * @param event The {@link AppTargetEvent} that represents the app target event.
     */
    public void notifyAppTargetEvent(@NonNull AppTargetEvent event) {
        if (mIsClosed.get()) {
            throw new IllegalStateException("This client has already been destroyed.");
        }

        try {
            mPredictionManager.notifyAppTargetEvent(mSessionId, event);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to notify app target event", e);
            e.rethrowAsRuntimeException();
        }
    }

    /**
     * Notifies the prediction service when the targets in a launch location are shown to the user.
     *
     * @param launchLocation The launch location where the targets are shown to the user.
     * @param targetIds List of {@link AppTargetId}s that are shown to the user.
     */
    public void notifyLaunchLocationShown(@NonNull String launchLocation,
            @NonNull List<AppTargetId> targetIds) {
        if (mIsClosed.get()) {
            throw new IllegalStateException("This client has already been destroyed.");
        }

        try {
            mPredictionManager.notifyLaunchLocationShown(mSessionId, launchLocation,
                    new ParceledListSlice<>(targetIds));
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to notify location shown event", e);
            e.rethrowAsRuntimeException();
        }
    }

    /**
     * Requests the prediction service provide continuous updates of App predictions via the
     * provided callback, until the given callback is unregistered.
     *
     * @see Callback#onTargetsAvailable(List).
     *
     * @param callbackExecutor The callback executor to use when calling the callback.
     * @param callback The Callback to be called when updates of App predictions are available.
     */
    public void registerPredictionUpdates(@NonNull @CallbackExecutor Executor callbackExecutor,
            @NonNull AppPredictor.Callback callback) {
        if (mIsClosed.get()) {
            throw new IllegalStateException("This client has already been destroyed.");
        }

        if (mRegisteredCallbacks.containsKey(callback)) {
            // Skip if this callback is already registered
            return;
        }
        try {
            final CallbackWrapper callbackWrapper = new CallbackWrapper(callbackExecutor,
                    callback::onTargetsAvailable);
            mPredictionManager.registerPredictionUpdates(mSessionId, callbackWrapper);
            mRegisteredCallbacks.put(callback, callbackWrapper);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to register for prediction updates", e);
            e.rethrowAsRuntimeException();
        }
    }

    /**
     * Requests the prediction service to stop providing continuous updates to the provided
     * callback until the callback is re-registered.
     *
     * @see {@link AppPredictor#registerPredictionUpdates(Executor, Callback)}.
     *
     * @param callback The callback to be unregistered.
     */
    public void unregisterPredictionUpdates(@NonNull AppPredictor.Callback callback) {
        if (mIsClosed.get()) {
            throw new IllegalStateException("This client has already been destroyed.");
        }

        if (!mRegisteredCallbacks.containsKey(callback)) {
            // Skip if this callback was never registered
            return;
        }
        try {
            final CallbackWrapper callbackWrapper = mRegisteredCallbacks.remove(callback);
            mPredictionManager.unregisterPredictionUpdates(mSessionId, callbackWrapper);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to unregister for prediction updates", e);
            e.rethrowAsRuntimeException();
        }
    }

    /**
     * Requests the prediction service to dispatch a new set of App predictions via the provided
     * callback.
     *
     * @see Callback#onTargetsAvailable(List).
     */
    public void requestPredictionUpdate() {
        if (mIsClosed.get()) {
            throw new IllegalStateException("This client has already been destroyed.");
        }

        try {
            mPredictionManager.requestPredictionUpdate(mSessionId);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to request prediction update", e);
            e.rethrowAsRuntimeException();
        }
    }

    /**
     * Returns a new list of AppTargets sorted based on prediction rank or {@code null} if the
     * ranker is not available.
     *
     * @param targets List of app targets to be sorted.
     * @param callbackExecutor The callback executor to use when calling the callback.
     * @param callback The callback to return the sorted list of app targets.
     */
    @Nullable
    public void sortTargets(@NonNull List<AppTarget> targets,
            @NonNull Executor callbackExecutor, @NonNull Consumer<List<AppTarget>> callback) {
        if (mIsClosed.get()) {
            throw new IllegalStateException("This client has already been destroyed.");
        }

        try {
            mPredictionManager.sortAppTargets(mSessionId, new ParceledListSlice(targets),
                    new CallbackWrapper(callbackExecutor, callback));
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to sort targets", e);
            e.rethrowAsRuntimeException();
        }
    }

    /**
     * Destroys the client and unregisters the callback. Any method on this class after this call
     * with throw {@link IllegalStateException}.
     */
    public void destroy() {
        if (!mIsClosed.getAndSet(true)) {
            mCloseGuard.close();

            // Do destroy;
            try {
                mPredictionManager.onDestroyPredictionSession(mSessionId);
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to notify app target event", e);
                e.rethrowAsRuntimeException();
            }
        } else {
            throw new IllegalStateException("This client has already been destroyed.");
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (mCloseGuard != null) {
                mCloseGuard.warnIfOpen();
            }
            if (!mIsClosed.get()) {
                destroy();
            }
        } finally {
            super.finalize();
        }
    }

    /**
     * Returns the id of this prediction session.
     *
     * @hide
     */
    @TestApi
    public AppPredictionSessionId getSessionId() {
        return mSessionId;
    }

    /**
     * Callback for receiving prediction updates.
     */
    public interface Callback {

        /**
         * Called when a new set of predicted app targets are available.
         * @param targets Sorted list of predicted targets.
         */
        void onTargetsAvailable(@NonNull List<AppTarget> targets);
    }

    static class CallbackWrapper extends Stub {

        private final Consumer<List<AppTarget>> mCallback;
        private final Executor mExecutor;

        CallbackWrapper(@NonNull Executor callbackExecutor,
                @NonNull Consumer<List<AppTarget>> callback) {
            mCallback = callback;
            mExecutor = callbackExecutor;
        }

        @Override
        public void onResult(ParceledListSlice result) {
            final long identity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() -> mCallback.accept(result.getList()));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }
}
