/*
 * Copyright (C) 2017 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;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserManager;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RemoteViews;
import android.widget.TextView;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.RemoteInputView;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Singleton;

import dagger.Lazy;

/**
 * Class for handling remote input state over a set of notifications. This class handles things
 * like keeping notifications temporarily that were cancelled as a response to a remote input
 * interaction, keeping track of notifications to remove when NotificationPresenter is collapsed,
 * and handling clicks on remote views.
 */
@Singleton
public class NotificationRemoteInputManager implements Dumpable {
    public static final boolean ENABLE_REMOTE_INPUT =
            SystemProperties.getBoolean("debug.enable_remote_input", true);
    public static boolean FORCE_REMOTE_INPUT_HISTORY =
            SystemProperties.getBoolean("debug.force_remoteinput_history", true);
    private static final boolean DEBUG = false;
    private static final String TAG = "NotifRemoteInputManager";

    /**
     * How long to wait before auto-dismissing a notification that was kept for remote input, and
     * has now sent a remote input. We auto-dismiss, because the app may not see a reason to cancel
     * these given that they technically don't exist anymore. We wait a bit in case the app issues
     * an update.
     */
    private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200;

    /**
     * Notifications that are already removed but are kept around because we want to show the
     * remote input history. See {@link RemoteInputHistoryExtender} and
     * {@link SmartReplyHistoryExtender}.
     */
    protected final ArraySet<String> mKeysKeptForRemoteInputHistory = new ArraySet<>();

    /**
     * Notifications that are already removed but are kept around because the remote input is
     * actively being used (i.e. user is typing in it).  See {@link RemoteInputActiveExtender}.
     */
    protected final ArraySet<NotificationEntry> mEntriesKeptForRemoteInputActive =
            new ArraySet<>();

    // Dependencies:
    private final NotificationLockscreenUserManager mLockscreenUserManager;
    private final SmartReplyController mSmartReplyController;
    private final NotificationEntryManager mEntryManager;
    private final Handler mMainHandler;

    private final Lazy<ShadeController> mShadeController;

    protected final Context mContext;
    private final UserManager mUserManager;
    private final KeyguardManager mKeyguardManager;
    private final StatusBarStateController mStatusBarStateController;

    protected RemoteInputController mRemoteInputController;
    protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
            mNotificationLifetimeFinishedCallback;
    protected IStatusBarService mBarService;
    protected Callback mCallback;
    protected final ArrayList<NotificationLifetimeExtender> mLifetimeExtenders = new ArrayList<>();

    private final RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {

        @Override
        public boolean onClickHandler(
                View view, PendingIntent pendingIntent, RemoteViews.RemoteResponse response) {
            mShadeController.get().wakeUpIfDozing(SystemClock.uptimeMillis(), view,
                    "NOTIFICATION_CLICK");

            if (handleRemoteInput(view, pendingIntent)) {
                return true;
            }

            if (DEBUG) {
                Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
            }
            logActionClick(view, pendingIntent);
            // The intent we are sending is for the application, which
            // won't have permission to immediately start an activity after
            // the user switches to home.  We know it is safe to do at this
            // point, so make sure new activity switches are now allowed.
            try {
                ActivityManager.getService().resumeAppSwitches();
            } catch (RemoteException e) {
            }
            return mCallback.handleRemoteViewClick(view, pendingIntent, () -> {
                Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view);
                options.second.setLaunchWindowingMode(
                        WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
                return RemoteViews.startPendingIntent(view, pendingIntent, options);
            });
        }

        private void logActionClick(View view, PendingIntent actionIntent) {
            Integer actionIndex = (Integer)
                    view.getTag(com.android.internal.R.id.notification_action_index_tag);
            if (actionIndex == null) {
                // Custom action button, not logging.
                return;
            }
            ViewParent parent = view.getParent();
            StatusBarNotification statusBarNotification = getNotificationForParent(parent);
            if (statusBarNotification == null) {
                Log.w(TAG, "Couldn't determine notification for click.");
                return;
            }
            String key = statusBarNotification.getKey();
            int buttonIndex = -1;
            // If this is a default template, determine the index of the button.
            if (view.getId() == com.android.internal.R.id.action0 &&
                    parent != null && parent instanceof ViewGroup) {
                ViewGroup actionGroup = (ViewGroup) parent;
                buttonIndex = actionGroup.indexOfChild(view);
            }
            final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
            final int rank = mEntryManager.getNotificationData().getRank(key);

            // Notification may be updated before this function is executed, and thus play safe
            // here and verify that the action object is still the one that where the click happens.
            Notification.Action[] actions = statusBarNotification.getNotification().actions;
            if (actions == null || actionIndex >= actions.length) {
                Log.w(TAG, "statusBarNotification.getNotification().actions is null or invalid");
                return;
            }
            final Notification.Action action =
                    statusBarNotification.getNotification().actions[actionIndex];
            if (!Objects.equals(action.actionIntent, actionIntent)) {
                Log.w(TAG, "actionIntent does not match");
                return;
            }
            NotificationVisibility.NotificationLocation location =
                    NotificationLogger.getNotificationLocation(
                            mEntryManager.getNotificationData().get(key));
            final NotificationVisibility nv =
                    NotificationVisibility.obtain(key, rank, count, true, location);
            try {
                mBarService.onNotificationActionClick(key, buttonIndex, action, nv, false);
            } catch (RemoteException e) {
                // Ignore
            }
        }

        private StatusBarNotification getNotificationForParent(ViewParent parent) {
            while (parent != null) {
                if (parent instanceof ExpandableNotificationRow) {
                    return ((ExpandableNotificationRow) parent).getStatusBarNotification();
                }
                parent = parent.getParent();
            }
            return null;
        }

        private boolean handleRemoteInput(View view, PendingIntent pendingIntent) {
            if (mCallback.shouldHandleRemoteInput(view, pendingIntent)) {
                return true;
            }

            Object tag = view.getTag(com.android.internal.R.id.remote_input_tag);
            RemoteInput[] inputs = null;
            if (tag instanceof RemoteInput[]) {
                inputs = (RemoteInput[]) tag;
            }

            if (inputs == null) {
                return false;
            }

            RemoteInput input = null;

            for (RemoteInput i : inputs) {
                if (i.getAllowFreeFormInput()) {
                    input = i;
                }
            }

            if (input == null) {
                return false;
            }

            return activateRemoteInput(view, inputs, input, pendingIntent,
                    null /* editedSuggestionInfo */);
        }
    };

    @Inject
    public NotificationRemoteInputManager(
            Context context,
            NotificationLockscreenUserManager lockscreenUserManager,
            SmartReplyController smartReplyController,
            NotificationEntryManager notificationEntryManager,
            Lazy<ShadeController> shadeController,
            StatusBarStateController statusBarStateController,
            @MainHandler Handler mainHandler) {
        mContext = context;
        mLockscreenUserManager = lockscreenUserManager;
        mSmartReplyController = smartReplyController;
        mEntryManager = notificationEntryManager;
        mShadeController = shadeController;
        mMainHandler = mainHandler;
        mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        addLifetimeExtenders();
        mKeyguardManager = context.getSystemService(KeyguardManager.class);
        mStatusBarStateController = statusBarStateController;

        notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
            @Override
            public void onPreEntryUpdated(NotificationEntry entry) {
                // Mark smart replies as sent whenever a notification is updated - otherwise the
                // smart replies are never marked as sent.
                mSmartReplyController.stopSending(entry);
            }

            @Override
            public void onEntryRemoved(
                    @Nullable NotificationEntry entry,
                    NotificationVisibility visibility,
                    boolean removedByUser) {
                // We're removing the notification, the smart controller can forget about it.
                mSmartReplyController.stopSending(entry);

                if (removedByUser && entry != null) {
                    onPerformRemoveNotification(entry, entry.getKey());
                }
            }
        });
    }

    /** Initializes this component with the provided dependencies. */
    public void setUpWithCallback(Callback callback, RemoteInputController.Delegate delegate) {
        mCallback = callback;
        mRemoteInputController = new RemoteInputController(delegate);
        mRemoteInputController.addCallback(new RemoteInputController.Callback() {
            @Override
            public void onRemoteInputSent(NotificationEntry entry) {
                if (FORCE_REMOTE_INPUT_HISTORY
                        && isNotificationKeptForRemoteInputHistory(entry.getKey())) {
                    mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
                } else if (mEntriesKeptForRemoteInputActive.contains(entry)) {
                    // We're currently holding onto this notification, but from the apps point of
                    // view it is already canceled, so we'll need to cancel it on the apps behalf
                    // after sending - unless the app posts an update in the mean time, so wait a
                    // bit.
                    mMainHandler.postDelayed(() -> {
                        if (mEntriesKeptForRemoteInputActive.remove(entry)) {
                            mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
                        }
                    }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
                }
                try {
                    mBarService.onNotificationDirectReplied(entry.getSbn().getKey());
                    if (entry.editedSuggestionInfo != null) {
                        boolean modifiedBeforeSending =
                                !TextUtils.equals(entry.remoteInputText,
                                        entry.editedSuggestionInfo.originalText);
                        mBarService.onNotificationSmartReplySent(
                                entry.getSbn().getKey(),
                                entry.editedSuggestionInfo.index,
                                entry.editedSuggestionInfo.originalText,
                                NotificationLogger
                                        .getNotificationLocation(entry)
                                        .toMetricsEventEnum(),
                                modifiedBeforeSending);
                    }
                } catch (RemoteException e) {
                    // Nothing to do, system going down
                }
            }
        });
        mSmartReplyController.setCallback((entry, reply) -> {
            StatusBarNotification newSbn =
                    rebuildNotificationWithRemoteInput(entry, reply, true /* showSpinner */);
            mEntryManager.updateNotification(newSbn, null /* ranking */);
        });
    }

    /**
     * Activates a given {@link RemoteInput}
     *
     * @param view The view of the action button or suggestion chip that was tapped.
     * @param inputs The remote inputs that need to be sent to the app.
     * @param input The remote input that needs to be activated.
     * @param pendingIntent The pending intent to be sent to the app.
     * @param editedSuggestionInfo The smart reply that should be inserted in the remote input, or
     *         {@code null} if the user is not editing a smart reply.
     * @return Whether the {@link RemoteInput} was activated.
     */
    public boolean activateRemoteInput(View view, RemoteInput[] inputs, RemoteInput input,
            PendingIntent pendingIntent, @Nullable EditedSuggestionInfo editedSuggestionInfo) {

        ViewParent p = view.getParent();
        RemoteInputView riv = null;
        ExpandableNotificationRow row = null;
        while (p != null) {
            if (p instanceof View) {
                View pv = (View) p;
                if (pv.isRootNamespace()) {
                    riv = findRemoteInputView(pv);
                    row = (ExpandableNotificationRow) pv.getTag(R.id.row_tag_for_content_view);
                    break;
                }
            }
            p = p.getParent();
        }

        if (row == null) {
            return false;
        }

        row.setUserExpanded(true);

        if (!mLockscreenUserManager.shouldAllowLockscreenRemoteInput()) {
            final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
            if (mLockscreenUserManager.isLockscreenPublicMode(userId)
                    || mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                // Even if we don't have security we should go through this flow, otherwise we won't
                // go to the shade
                mCallback.onLockedRemoteInput(row, view);
                return true;
            }
            if (mUserManager.getUserInfo(userId).isManagedProfile()
                    && mKeyguardManager.isDeviceLocked(userId)) {
                mCallback.onLockedWorkRemoteInput(userId, row, view);
                return true;
            }
        }

        if (riv != null && !riv.isAttachedToWindow()) {
            // the remoteInput isn't attached to the window anymore :/ Let's focus on the expanded
            // one instead if it's available
            riv = null;
        }
        if (riv == null) {
            riv = findRemoteInputView(row.getPrivateLayout().getExpandedChild());
            if (riv == null) {
                return false;
            }
        }
        if (riv == row.getPrivateLayout().getExpandedRemoteInput()
                && !row.getPrivateLayout().getExpandedChild().isShown()) {
            // The expanded layout is selected, but it's not shown yet, let's wait on it to
            // show before we do the animation.
            mCallback.onMakeExpandedVisibleForRemoteInput(row, view);
            return true;
        }

        if (!riv.isAttachedToWindow()) {
            // if we still didn't find a view that is attached, let's abort.
            return false;
        }
        int width = view.getWidth();
        if (view instanceof TextView) {
            // Center the reveal on the text which might be off-center from the TextView
            TextView tv = (TextView) view;
            if (tv.getLayout() != null) {
                int innerWidth = (int) tv.getLayout().getLineWidth(0);
                innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
                width = Math.min(width, innerWidth);
            }
        }
        int cx = view.getLeft() + width / 2;
        int cy = view.getTop() + view.getHeight() / 2;
        int w = riv.getWidth();
        int h = riv.getHeight();
        int r = Math.max(
                Math.max(cx + cy, cx + (h - cy)),
                Math.max((w - cx) + cy, (w - cx) + (h - cy)));

        riv.setRevealParameters(cx, cy, r);
        riv.setPendingIntent(pendingIntent);
        riv.setRemoteInput(inputs, input, editedSuggestionInfo);
        riv.focusAnimated();

        return true;
    }

    private RemoteInputView findRemoteInputView(View v) {
        if (v == null) {
            return null;
        }
        return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG);
    }

    /**
     * Adds all the notification lifetime extenders. Each extender represents a reason for the
     * NotificationRemoteInputManager to keep a notification lifetime extended.
     */
    protected void addLifetimeExtenders() {
        mLifetimeExtenders.add(new RemoteInputHistoryExtender());
        mLifetimeExtenders.add(new SmartReplyHistoryExtender());
        mLifetimeExtenders.add(new RemoteInputActiveExtender());
    }

    public ArrayList<NotificationLifetimeExtender> getLifetimeExtenders() {
        return mLifetimeExtenders;
    }

    public RemoteInputController getController() {
        return mRemoteInputController;
    }

    @VisibleForTesting
    void onPerformRemoveNotification(NotificationEntry entry, final String key) {
        if (mKeysKeptForRemoteInputHistory.contains(key)) {
            mKeysKeptForRemoteInputHistory.remove(key);
        }
        if (mRemoteInputController.isRemoteInputActive(entry)) {
            mRemoteInputController.removeRemoteInput(entry, null);
        }
    }

    public void onPanelCollapsed() {
        for (int i = 0; i < mEntriesKeptForRemoteInputActive.size(); i++) {
            NotificationEntry entry = mEntriesKeptForRemoteInputActive.valueAt(i);
            mRemoteInputController.removeRemoteInput(entry, null);
            if (mNotificationLifetimeFinishedCallback != null) {
                mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
            }
        }
        mEntriesKeptForRemoteInputActive.clear();
    }

    public boolean isNotificationKeptForRemoteInputHistory(String key) {
        return mKeysKeptForRemoteInputHistory.contains(key);
    }

    public boolean shouldKeepForRemoteInputHistory(NotificationEntry entry) {
        if (!FORCE_REMOTE_INPUT_HISTORY) {
            return false;
        }
        return (mRemoteInputController.isSpinning(entry.getKey())
                || entry.hasJustSentRemoteInput());
    }

    public boolean shouldKeepForSmartReplyHistory(NotificationEntry entry) {
        if (!FORCE_REMOTE_INPUT_HISTORY) {
            return false;
        }
        return mSmartReplyController.isSendingSmartReply(entry.getKey());
    }

    public void checkRemoteInputOutside(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar
                && event.getX() == 0 && event.getY() == 0  // a touch outside both bars
                && mRemoteInputController.isRemoteInputActive()) {
            mRemoteInputController.closeRemoteInputs();
        }
    }

    @VisibleForTesting
    StatusBarNotification rebuildNotificationForCanceledSmartReplies(
            NotificationEntry entry) {
        return rebuildNotificationWithRemoteInput(entry, null /* remoteInputTest */,
                false /* showSpinner */);
    }

    @VisibleForTesting
    StatusBarNotification rebuildNotificationWithRemoteInput(NotificationEntry entry,
            CharSequence remoteInputText, boolean showSpinner) {
        StatusBarNotification sbn = entry.getSbn();

        Notification.Builder b = Notification.Builder
                .recoverBuilder(mContext, sbn.getNotification().clone());
        if (remoteInputText != null) {
            CharSequence[] oldHistory = sbn.getNotification().extras
                    .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
            CharSequence[] newHistory;
            if (oldHistory == null) {
                newHistory = new CharSequence[1];
            } else {
                newHistory = new CharSequence[oldHistory.length + 1];
                System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length);
            }
            newHistory[0] = String.valueOf(remoteInputText);
            b.setRemoteInputHistory(newHistory);
        }
        b.setShowRemoteInputSpinner(showSpinner);
        b.setHideSmartReplies(true);

        Notification newNotification = b.build();

        // Undo any compatibility view inflation
        newNotification.contentView = sbn.getNotification().contentView;
        newNotification.bigContentView = sbn.getNotification().bigContentView;
        newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;

        return new StatusBarNotification(
                sbn.getPackageName(),
                sbn.getOpPkg(),
                sbn.getId(),
                sbn.getTag(),
                sbn.getUid(),
                sbn.getInitialPid(),
                newNotification,
                sbn.getUser(),
                sbn.getOverrideGroupKey(),
                sbn.getPostTime());
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("NotificationRemoteInputManager state:");
        pw.print("  mKeysKeptForRemoteInputHistory: ");
        pw.println(mKeysKeptForRemoteInputHistory);
        pw.print("  mEntriesKeptForRemoteInputActive: ");
        pw.println(mEntriesKeptForRemoteInputActive);
    }

    public void bindRow(ExpandableNotificationRow row) {
        row.setRemoteInputController(mRemoteInputController);
        row.setRemoteViewClickHandler(mOnClickHandler);
    }

    @VisibleForTesting
    public Set<NotificationEntry> getEntriesKeptForRemoteInputActive() {
        return mEntriesKeptForRemoteInputActive;
    }

    /**
     * NotificationRemoteInputManager has multiple reasons to keep notification lifetime extended
     * so we implement multiple NotificationLifetimeExtenders
     */
    protected abstract class RemoteInputExtender implements NotificationLifetimeExtender {
        @Override
        public void setCallback(NotificationSafeToRemoveCallback callback) {
            if (mNotificationLifetimeFinishedCallback == null) {
                mNotificationLifetimeFinishedCallback = callback;
            }
        }
    }

    /**
     * Notification is kept alive as it was cancelled in response to a remote input interaction.
     * This allows us to show what you replied and allows you to continue typing into it.
     */
    protected class RemoteInputHistoryExtender extends RemoteInputExtender {
        @Override
        public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
            return shouldKeepForRemoteInputHistory(entry);
        }

        @Override
        public void setShouldManageLifetime(NotificationEntry entry,
                boolean shouldExtend) {
            if (shouldExtend) {
                CharSequence remoteInputText = entry.remoteInputText;
                if (TextUtils.isEmpty(remoteInputText)) {
                    remoteInputText = entry.remoteInputTextWhenReset;
                }
                StatusBarNotification newSbn = rebuildNotificationWithRemoteInput(entry,
                        remoteInputText, false /* showSpinner */);
                entry.onRemoteInputInserted();

                if (newSbn == null) {
                    return;
                }

                mEntryManager.updateNotification(newSbn, null);

                // Ensure the entry hasn't already been removed. This can happen if there is an
                // inflation exception while updating the remote history
                if (entry.isRemoved()) {
                    return;
                }

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Keeping notification around after sending remote input "
                            + entry.getKey());
                }

                mKeysKeptForRemoteInputHistory.add(entry.getKey());
            } else {
                mKeysKeptForRemoteInputHistory.remove(entry.getKey());
            }
        }
    }

    /**
     * Notification is kept alive for smart reply history.  Similar to REMOTE_INPUT_HISTORY but with
     * {@link SmartReplyController} specific logic
     */
    protected class SmartReplyHistoryExtender extends RemoteInputExtender {
        @Override
        public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
            return shouldKeepForSmartReplyHistory(entry);
        }

        @Override
        public void setShouldManageLifetime(NotificationEntry entry,
                boolean shouldExtend) {
            if (shouldExtend) {
                StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry);

                if (newSbn == null) {
                    return;
                }

                mEntryManager.updateNotification(newSbn, null);

                if (entry.isRemoved()) {
                    return;
                }

                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Keeping notification around after sending smart reply "
                            + entry.getKey());
                }

                mKeysKeptForRemoteInputHistory.add(entry.getKey());
            } else {
                mKeysKeptForRemoteInputHistory.remove(entry.getKey());
                mSmartReplyController.stopSending(entry);
            }
        }
    }

    /**
     * Notification is kept alive because the user is still using the remote input
     */
    protected class RemoteInputActiveExtender extends RemoteInputExtender {
        @Override
        public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
            return mRemoteInputController.isRemoteInputActive(entry);
        }

        @Override
        public void setShouldManageLifetime(NotificationEntry entry,
                boolean shouldExtend) {
            if (shouldExtend) {
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Keeping notification around while remote input active "
                            + entry.getKey());
                }
                mEntriesKeptForRemoteInputActive.add(entry);
            } else {
                mEntriesKeptForRemoteInputActive.remove(entry);
            }
        }
    }

    /**
     * Callback for various remote input related events, or for providing information that
     * NotificationRemoteInputManager needs to know to decide what to do.
     */
    public interface Callback {

        /**
         * Called when remote input was activated but the device is locked.
         *
         * @param row
         * @param clicked
         */
        void onLockedRemoteInput(ExpandableNotificationRow row, View clicked);

        /**
         * Called when remote input was activated but the device is locked and in a managed profile.
         *
         * @param userId
         * @param row
         * @param clicked
         */
        void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, View clicked);

        /**
         * Called when a row should be made expanded for the purposes of remote input.
         *
         * @param row
         * @param clickedView
         */
        void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, View clickedView);

        /**
         * Return whether or not remote input should be handled for this view.
         *
         * @param view
         * @param pendingIntent
         * @return true iff the remote input should be handled
         */
        boolean shouldHandleRemoteInput(View view, PendingIntent pendingIntent);

        /**
         * Performs any special handling for a remote view click. The default behaviour can be
         * called through the defaultHandler parameter.
         *
         * @param view
         * @param pendingIntent
         * @param defaultHandler
         * @return  true iff the click was handled
         */
        boolean handleRemoteViewClick(View view, PendingIntent pendingIntent,
                ClickHandler defaultHandler);
    }

    /**
     * Helper interface meant for passing the default on click behaviour to NotificationPresenter,
     * so it may do its own handling before invoking the default behaviour.
     */
    public interface ClickHandler {
        /**
         * Tries to handle a click on a remote view.
         *
         * @return true iff the click was handled
         */
        boolean handleClick();
    }
}
