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

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.graphics.Bitmap;
import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.util.SyncResultReceiver;

import java.util.List;
import java.util.concurrent.Executor;

/**
 * When provided with content from an app, can suggest selections and classifications of that
 * content.
 *
 * <p>The content is mainly a snapshot of a running task, the selections will be text and image
 * selections with that image content. These mSelections can then be classified to find actions and
 * entities on those selections.
 *
 * <p>Only accessible to blessed components such as Overview.
 *
 * @hide
 */
@SystemApi
public final class ContentSuggestionsManager {
    /**
     * Key into the extras Bundle passed to {@link #provideContextImage(int, Bundle)}.
     * This can be used to provide the bitmap to
     * {@link android.service.contentsuggestions.ContentSuggestionsService}.
     * The value must be a {@link android.graphics.Bitmap} with the
     * config {@link android.graphics.Bitmap.Config.HARDWARE}.
     *
     * @hide
     */
    public static final String EXTRA_BITMAP = "android.contentsuggestions.extra.BITMAP";

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

    /**
     * Timeout for calls to system_server.
     */
    private static final int SYNC_CALLS_TIMEOUT_MS = 5000;

    @Nullable
    private final IContentSuggestionsManager mService;

    @NonNull
    private final int mUser;

    /** @hide */
    public ContentSuggestionsManager(
            @UserIdInt int userId, @Nullable IContentSuggestionsManager service) {
        mService = service;
        mUser = userId;
    }

    /**
     * Hints to the system that a new context image using the provided bitmap should be sent to
     * the system content suggestions service.
     *
     * @param bitmap the new context image
     * @param imageContextRequestExtras sent with request to provide implementation specific
     *                                  extra information.
     */
    public void provideContextImage(
            @NonNull Bitmap bitmap, @NonNull Bundle imageContextRequestExtras) {
        if (mService == null) {
            Log.e(TAG, "provideContextImage called, but no ContentSuggestionsManager configured");
            return;
        }

        try {
            mService.provideContextBitmap(mUser, bitmap, imageContextRequestExtras);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Hints to the system that a new context image for the provided task should be sent to the
     * system content suggestions service.
     *
     * @param taskId of the task to snapshot.
     * @param imageContextRequestExtras sent with request to provide implementation specific
     *                                  extra information.
     */
    public void provideContextImage(
            int taskId, @NonNull Bundle imageContextRequestExtras) {
        if (mService == null) {
            Log.e(TAG, "provideContextImage called, but no ContentSuggestionsManager configured");
            return;
        }

        try {
            mService.provideContextImage(mUser, taskId, imageContextRequestExtras);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Suggest content selections, based on the provided task id and optional
     * location on screen provided in the request. Called after provideContextImage().
     * The result can be passed to
     * {@link #classifyContentSelections(ClassificationsRequest, Executor, ClassificationsCallback)}
     *  to classify actions and entities on these selections.
     *
     * @param request containing the task and point location.
     * @param callbackExecutor to execute the provided callback on.
     * @param callback to receive the selections.
     */
    public void suggestContentSelections(
            @NonNull SelectionsRequest request,
            @NonNull @CallbackExecutor Executor callbackExecutor,
            @NonNull SelectionsCallback callback) {
        if (mService == null) {
            Log.e(TAG,
                    "suggestContentSelections called, but no ContentSuggestionsManager configured");
            return;
        }

        try {
            mService.suggestContentSelections(
                    mUser, request, new SelectionsCallbackWrapper(callback, callbackExecutor));
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Classify actions and entities in content selections, as returned from
     * suggestContentSelections. Note these selections may be modified by the
     * caller before being passed here.
     *
     * @param request containing the selections to classify.
     * @param callbackExecutor to execute the provided callback on.
     * @param callback to receive the classifications.
     */
    public void classifyContentSelections(
            @NonNull ClassificationsRequest request,
            @NonNull @CallbackExecutor Executor callbackExecutor,
            @NonNull ClassificationsCallback callback) {
        if (mService == null) {
            Log.e(TAG, "classifyContentSelections called, "
                    + "but no ContentSuggestionsManager configured");
            return;
        }

        try {
            mService.classifyContentSelections(
                    mUser, request, new ClassificationsCallbackWrapper(callback, callbackExecutor));
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Report telemetry for interaction with suggestions / classifications.
     *
     * @param requestId the id for the associated interaction
     * @param interaction to report back to the system content suggestions service.
     */
    public void notifyInteraction(
            @NonNull String requestId, @NonNull Bundle interaction) {
        if (mService == null) {
            Log.e(TAG, "notifyInteraction called, but no ContentSuggestionsManager configured");
            return;
        }

        try {
            mService.notifyInteraction(mUser, requestId, interaction);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Indicates that Content Suggestions is available and enabled for the provided user. That is,
     * has an implementation and not disabled through device management.
     *
     * @return {@code true} if Content Suggestions is enabled and available for the provided user.
     */
    public boolean isEnabled() {
        if (mService == null) {
            return false;
        }

        SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
        try {
            mService.isEnabled(mUser, receiver);
            return receiver.getIntResult() != 0;
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        return false;
    }

    /**
     * Callback to receive content selections from
     *  {@link #suggestContentSelections(SelectionsRequest, Executor, SelectionsCallback)}.
     */
    public interface SelectionsCallback {
        /**
         * Async callback called when the content suggestions service has selections available.
         * These can be modified and sent back to the manager for classification. The contents of
         * the selection is implementation dependent.
         *
         * @param statusCode as defined by the implementation of content suggestions service.
         * @param selections not {@code null}, but can be size {@code 0}.
         */
        void onContentSelectionsAvailable(
                int statusCode, @NonNull List<ContentSelection> selections);
    }

    /**
     * Callback to receive classifications from
     * {@link #classifyContentSelections(ClassificationsRequest, Executor, ClassificationsCallback)}
     */
    public interface ClassificationsCallback {
        /**
         * Async callback called when the content suggestions service has classified selections. The
         * contents of the classification is implementation dependent.
         *
         * @param statusCode as defined by the implementation of content suggestions service.
         * @param classifications not {@code null}, but can be size {@code 0}.
         */
        void onContentClassificationsAvailable(int statusCode,
                @NonNull List<ContentClassification> classifications);
    }

    private static class SelectionsCallbackWrapper extends ISelectionsCallback.Stub {
        private final SelectionsCallback mCallback;
        private final Executor mExecutor;

        SelectionsCallbackWrapper(
                @NonNull SelectionsCallback callback, @NonNull Executor executor) {
            mCallback = callback;
            mExecutor = executor;
        }

        @Override
        public void onContentSelectionsAvailable(
                int statusCode, List<ContentSelection> selections) {
            final long identity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() ->
                        mCallback.onContentSelectionsAvailable(statusCode, selections));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    private static final class ClassificationsCallbackWrapper extends
            IClassificationsCallback.Stub {
        private final ClassificationsCallback mCallback;
        private final Executor mExecutor;

        ClassificationsCallbackWrapper(@NonNull ClassificationsCallback callback,
                @NonNull Executor executor) {
            mCallback = callback;
            mExecutor = executor;
        }

        @Override
        public void onContentClassificationsAvailable(
                int statusCode, List<ContentClassification> classifications) {
            final long identity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() ->
                        mCallback.onContentClassificationsAvailable(statusCode, classifications));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }
}
