/*
 * Copyright (C) 2019 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 com.android.systemui.statusbar.policy;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.util.Log;
import android.util.Pair;
import android.widget.Button;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.Dependency;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Holder for inflated smart replies and actions. These objects should be inflated on a background
 * thread, to later be accessed and modified on the (performance critical) UI thread.
 */
public class InflatedSmartReplies {
    private static final String TAG = "InflatedSmartReplies";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    @Nullable private final SmartReplyView mSmartReplyView;
    @Nullable private final List<Button> mSmartSuggestionButtons;
    @NonNull private final SmartRepliesAndActions mSmartRepliesAndActions;

    private InflatedSmartReplies(
            @Nullable SmartReplyView smartReplyView,
            @Nullable List<Button> smartSuggestionButtons,
            @NonNull SmartRepliesAndActions smartRepliesAndActions) {
        mSmartReplyView = smartReplyView;
        mSmartSuggestionButtons = smartSuggestionButtons;
        mSmartRepliesAndActions = smartRepliesAndActions;
    }

    @Nullable public SmartReplyView getSmartReplyView() {
        return mSmartReplyView;
    }

    @Nullable public List<Button> getSmartSuggestionButtons() {
        return mSmartSuggestionButtons;
    }

    @NonNull public SmartRepliesAndActions getSmartRepliesAndActions() {
        return mSmartRepliesAndActions;
    }

    /**
     * Inflate a SmartReplyView and its smart suggestions.
     */
    public static InflatedSmartReplies inflate(
            Context context,
            Context packageContext,
            NotificationEntry entry,
            SmartReplyConstants smartReplyConstants,
            SmartReplyController smartReplyController,
            HeadsUpManager headsUpManager,
            SmartRepliesAndActions existingSmartRepliesAndActions) {
        SmartRepliesAndActions newSmartRepliesAndActions =
                chooseSmartRepliesAndActions(smartReplyConstants, entry);
        if (!shouldShowSmartReplyView(entry, newSmartRepliesAndActions)) {
            return new InflatedSmartReplies(null /* smartReplyView */,
                    null /* smartSuggestionButtons */, newSmartRepliesAndActions);
        }

        // Only block clicks if the smart buttons are different from the previous set - to avoid
        // scenarios where a user incorrectly cannot click smart buttons because the notification is
        // updated.
        boolean delayOnClickListener =
                !areSuggestionsSimilar(existingSmartRepliesAndActions, newSmartRepliesAndActions);

        SmartReplyView smartReplyView = SmartReplyView.inflate(context);

        List<Button> suggestionButtons = new ArrayList<>();
        if (newSmartRepliesAndActions.smartReplies != null) {
            suggestionButtons.addAll(smartReplyView.inflateRepliesFromRemoteInput(
                    newSmartRepliesAndActions.smartReplies, smartReplyController, entry,
                    delayOnClickListener));
        }
        if (newSmartRepliesAndActions.smartActions != null) {
            suggestionButtons.addAll(
                    smartReplyView.inflateSmartActions(packageContext,
                            newSmartRepliesAndActions.smartActions, smartReplyController, entry,
                            headsUpManager, delayOnClickListener));
        }

        return new InflatedSmartReplies(smartReplyView, suggestionButtons,
                newSmartRepliesAndActions);
    }

    @VisibleForTesting
    static boolean areSuggestionsSimilar(
            SmartRepliesAndActions left, SmartRepliesAndActions right) {
        if (left == right) return true;
        if (left == null || right == null) return false;

        if (!Arrays.equals(left.getSmartReplies(), right.getSmartReplies())) {
            return false;
        }

        return !NotificationUiAdjustment.areDifferent(
                left.getSmartActions(), right.getSmartActions());
    }

    /**
     * Returns whether we should show the smart reply view and its smart suggestions.
     */
    public static boolean shouldShowSmartReplyView(
            NotificationEntry entry,
            SmartRepliesAndActions smartRepliesAndActions) {
        if (smartRepliesAndActions.smartReplies == null
                && smartRepliesAndActions.smartActions == null) {
            // There are no smart replies and no smart actions.
            return false;
        }
        // If we are showing the spinner we don't want to add the buttons.
        boolean showingSpinner = entry.notification.getNotification()
                .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
        if (showingSpinner) {
            return false;
        }
        // If we are keeping the notification around while sending we don't want to add the buttons.
        boolean hideSmartReplies = entry.notification.getNotification()
                .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
        if (hideSmartReplies) {
            return false;
        }
        return true;
    }

    /**
     * Chose what smart replies and smart actions to display. App generated suggestions take
     * precedence. So if the app provides any smart replies, we don't show any
     * replies or actions generated by the NotificationAssistantService (NAS), and if the app
     * provides any smart actions we also don't show any NAS-generated replies or actions.
     */
    @NonNull
    public static SmartRepliesAndActions chooseSmartRepliesAndActions(
            SmartReplyConstants smartReplyConstants,
            final NotificationEntry entry) {
        Notification notification = entry.notification.getNotification();
        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
                notification.findRemoteInputActionPair(false /* freeform */);
        Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
                notification.findRemoteInputActionPair(true /* freeform */);

        if (!smartReplyConstants.isEnabled()) {
            if (DEBUG) {
                Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
                        + entry.notification.getKey());
            }
            return new SmartRepliesAndActions(null, null);
        }
        // Only use smart replies from the app if they target P or above. We have this check because
        // the smart reply API has been used for other things (Wearables) in the past. The API to
        // add smart actions is new in Q so it doesn't require a target-sdk check.
        boolean enableAppGeneratedSmartReplies = (!smartReplyConstants.requiresTargetingP()
                || entry.targetSdk >= Build.VERSION_CODES.P);

        boolean appGeneratedSmartRepliesExist =
                enableAppGeneratedSmartReplies
                        && remoteInputActionPair != null
                        && !ArrayUtils.isEmpty(remoteInputActionPair.first.getChoices())
                        && remoteInputActionPair.second.actionIntent != null;

        List<Notification.Action> appGeneratedSmartActions = notification.getContextualActions();
        boolean appGeneratedSmartActionsExist = !appGeneratedSmartActions.isEmpty();

        SmartReplyView.SmartReplies smartReplies = null;
        SmartReplyView.SmartActions smartActions = null;
        if (appGeneratedSmartRepliesExist) {
            smartReplies = new SmartReplyView.SmartReplies(
                    remoteInputActionPair.first.getChoices(),
                    remoteInputActionPair.first,
                    remoteInputActionPair.second.actionIntent,
                    false /* fromAssistant */);
        }
        if (appGeneratedSmartActionsExist) {
            smartActions = new SmartReplyView.SmartActions(appGeneratedSmartActions,
                    false /* fromAssistant */);
        }
        // Apps didn't provide any smart replies / actions, use those from NAS (if any).
        if (!appGeneratedSmartRepliesExist && !appGeneratedSmartActionsExist) {
            boolean useGeneratedReplies = !ArrayUtils.isEmpty(entry.systemGeneratedSmartReplies)
                    && freeformRemoteInputActionPair != null
                    && freeformRemoteInputActionPair.second.getAllowGeneratedReplies()
                    && freeformRemoteInputActionPair.second.actionIntent != null;
            if (useGeneratedReplies) {
                smartReplies = new SmartReplyView.SmartReplies(
                        entry.systemGeneratedSmartReplies,
                        freeformRemoteInputActionPair.first,
                        freeformRemoteInputActionPair.second.actionIntent,
                        true /* fromAssistant */);
            }
            boolean useSmartActions = !ArrayUtils.isEmpty(entry.systemGeneratedSmartActions)
                    && notification.getAllowSystemGeneratedContextualActions();
            if (useSmartActions) {
                List<Notification.Action> systemGeneratedActions =
                        entry.systemGeneratedSmartActions;
                // Filter actions if we're in kiosk-mode - we don't care about screen pinning mode,
                // since notifications aren't shown there anyway.
                ActivityManagerWrapper activityManagerWrapper =
                        Dependency.get(ActivityManagerWrapper.class);
                if (activityManagerWrapper.isLockTaskKioskModeActive()) {
                    systemGeneratedActions = filterWhiteListedLockTaskApps(systemGeneratedActions);
                }
                smartActions = new SmartReplyView.SmartActions(
                        systemGeneratedActions, true /* fromAssistant */);
            }
        }
        return new SmartRepliesAndActions(smartReplies, smartActions);
    }

    /**
     * Filter actions so that only actions pointing to whitelisted apps are allowed.
     * This filtering is only meaningful when in lock-task mode.
     */
    private static List<Notification.Action> filterWhiteListedLockTaskApps(
            List<Notification.Action> actions) {
        PackageManagerWrapper packageManagerWrapper = Dependency.get(PackageManagerWrapper.class);
        DevicePolicyManagerWrapper devicePolicyManagerWrapper =
                Dependency.get(DevicePolicyManagerWrapper.class);
        List<Notification.Action> filteredActions = new ArrayList<>();
        for (Notification.Action action : actions) {
            if (action.actionIntent == null) continue;
            Intent intent = action.actionIntent.getIntent();
            //  Only allow actions that are explicit (implicit intents are not handled in lock-task
            //  mode), and link to whitelisted apps.
            ResolveInfo resolveInfo = packageManagerWrapper.resolveActivity(intent, 0 /* flags */);
            if (resolveInfo != null && devicePolicyManagerWrapper.isLockTaskPermitted(
                    resolveInfo.activityInfo.packageName)) {
                filteredActions.add(action);
            }
        }
        return filteredActions;
    }

    /**
     * Returns whether the {@link Notification} represented by entry has a free-form remote input.
     * Such an input can be used e.g. to implement smart reply buttons - by passing the replies
     * through the remote input.
     */
    public static boolean hasFreeformRemoteInput(NotificationEntry entry) {
        Notification notification = entry.notification.getNotification();
        return null != notification.findRemoteInputActionPair(true /* freeform */);
    }

    /**
     * A storage for smart replies and smart action.
     */
    public static class SmartRepliesAndActions {
        @Nullable public final SmartReplyView.SmartReplies smartReplies;
        @Nullable public final SmartReplyView.SmartActions smartActions;

        SmartRepliesAndActions(
                @Nullable SmartReplyView.SmartReplies smartReplies,
                @Nullable SmartReplyView.SmartActions smartActions) {
            this.smartReplies = smartReplies;
            this.smartActions = smartActions;
        }

        @NonNull public CharSequence[] getSmartReplies() {
            return smartReplies == null ? new CharSequence[0] : smartReplies.choices;
        }

        @NonNull public List<Notification.Action> getSmartActions() {
            return smartActions == null ? Collections.emptyList() : smartActions.actions;
        }
    }
}
