/*
 * 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.cts.verifier.notifications;

import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.content.Intent.ACTION_VIEW;
import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;

import static com.android.cts.verifier.notifications.BubbleActivity.EXTRA_INSETS;
import static com.android.cts.verifier.notifications.BubbleActivity.EXTRA_TEST_NAME;
import static com.android.cts.verifier.notifications.BubbleActivity.TEST_MAX_HEIGHT;
import static com.android.cts.verifier.notifications.BubbleActivity.TEST_MIN_HEIGHT;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.ArraySet;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;
import android.widget.Button;
import android.widget.TextView;

import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;

import java.util.ArrayList;
import java.util.Set;

/**
 * Bubble notification tests: This test checks the behaviour of notifications that have a bubble.
 */
public class BubblesVerifierActivity extends PassFailButtons.Activity {

    private static final String CHANNEL_ID = "BubblesVerifierChannel";
    private static final int NOTIFICATION_ID = 1;
    private static final int NUM_SHORTCUTS = 3;
    private static final String SHORTCUT_CATEGORY =
            "com.android.cts.verifier.notifications.SHORTCUT_CATEGORY";

    private NotificationManager mNotificationManager;
    private ArrayList<ShortcutInfo> mShortcuts = new ArrayList<>();
    private boolean mIsLargeScreen;

    private TextView mTestTitle;
    private TextView mTestDescription;
    private Button mTestAction;
    private ViewGroup mTestStepButtonLayout;
    private TextView mTestState;
    private Button mTestStepPassed;
    private Button mTestStepFailed;

    private ArrayList<BubblesTestStep> mTests = new ArrayList<>();
    private int mCurrentTestIndex = -1; // gets incremented first time
    private int mStepFailureCount = 0;
    private boolean mShowingSummary = false;

    private Handler mHandler = new Handler();
    private Runnable mRunnable;

    private abstract class BubblesTestStep {

        /** The title of the test step. */
        public abstract int getTestTitle();

        /** What the tester should do & look for to verify this step was successful. */
        public abstract int getTestDescription();

        /**
         * Text of the button that performs the action for this test (e.g. send bubble). If no
         * button is necessary this will return 0.
         */
        public int getButtonText() {
            return 0;
        }

        /** Code to run when the button is activated; only used if {@link #getButtonText()} != 0 */
        public void performTestAction() {
            // optional
        }

        /** Checks device state to see if the test passed.  */
        public boolean verify() {
            return true;
        }

        /** Return true if the test has stuff to check in {@link #verify()}. **/
        public boolean waitForVerify() {
            return false;
        }
    }

    @Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        setContentView(R.layout.bubbles_main);

        mTestTitle = findViewById(R.id.bubble_test_title);
        mTestDescription = findViewById(R.id.bubble_test_description);
        mTestAction = findViewById(R.id.bubble_test_button);
        mTestStepButtonLayout = findViewById(R.id.button_layout);
        mTestState = findViewById(R.id.bubble_test_state);
        mTestStepPassed = findViewById(R.id.test_step_passed);
        mTestStepFailed = findViewById(R.id.test_step_failed);

        mTestStepPassed.setOnClickListener((v) -> runNextTestOrShowSummary());
        mTestStepFailed.setOnClickListener((v) -> {
            mStepFailureCount++;
            runNextTestOrShowSummary();
        });

        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        if (am.isLowRamDevice()) {
            // Bubbles don't occur on low ram, instead they just show as notifs so test that
            mTests.add(new LowRamBubbleTest());
        } else if (!Resources.getSystem()
                    .getBoolean(com.android.internal.R.bool.config_supportsBubble)) {
            // Bubbles don't occur on bubble disabled devices, only test notifications.
            mTests.add(new BubbleDisabledTest());
        } else {
            //
            // Behavior around settings at the device level and on the app settings page.
            //
            mTests.add(new CheckDefaultsTest());
            mTests.add(new BubbleButtonTest());
            mTests.add(new BubblePreferenceSelected());
            mTests.add(new DisableFeature());
            mTests.add(new EnableBubblesTest());
            //
            // Behavior around visibility of the bubble, the notification, and the dot
            // on the bubble for 'new messages'.
            //
            mTests.add(new SendBubbleTest());
            mTests.add(new SuppressNotifTest());
            mTests.add(new AddNotifTest());
            mTests.add(new RemoveMetadataTest());
            mTests.add(new AddMetadataTest());
            mTests.add(new ExpandBubbleTest());
            mTests.add(new DismissBubbleTest());
            mTests.add(new DismissNotificationTest());
            mTests.add(new AutoExpandBubbleTest());
            //
            // Behavior around the bubble overflow
            //
            mTests.add(new CheckOverflowExists());
            mTests.add(new DismissBubbleShowsInOverflow());
            mTests.add(new PromoteBubbleFromOverflow());
            mTests.add(new CancelRemovesBubblesInOverflow());
            mTests.add(new TapNotifWithOverflowBubble());
            //
            // Expanded view appearance
            //
            mTests.add(new PortraitAndLandscape());
            mTests.add(new ScrimBehindExpandedView());
            mTests.add(new ImeInsetsExpandedView());
            mTests.add(new MinHeightExpandedView());
            mTests.add(new MaxHeightExpandedView());
        }

        setPassFailButtonClickListeners();
        // Pass is are enabled when all the steps are done & succeeded
        getPassButton().setEnabled(false);
        // Sets the text in the dialog
        setInfoResources(R.string.bubbles_test_title, R.string.bubbles_test_info, -1);

        mIsLargeScreen = getResources().getConfiguration().smallestScreenWidthDp >= 600;
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.createNotificationChannel(
                new NotificationChannel(CHANNEL_ID, CHANNEL_ID, IMPORTANCE_DEFAULT));
        createShortcuts();

        runNextTestOrShowSummary();

        restoreStateFromBundle(savedState);
    }

    @Override
    protected void onSaveInstanceState(Bundle savedState) {
        super.onSaveInstanceState(savedState);
        savedState.putInt("mCurrentTestIndex", mCurrentTestIndex);
        savedState.putInt("mStepFailureCount", mStepFailureCount);
        savedState.putBoolean("mShowingSummary", mShowingSummary);
        savedState.putBoolean("mTestStepPassed", mTestStepPassed.isEnabled());
    }

    private void restoreStateFromBundle(Bundle savedState) {
        if (savedState != null) {
            mCurrentTestIndex = savedState.getInt("mCurrentTestIndex", mCurrentTestIndex);
            mStepFailureCount = savedState.getInt("mStepFailureCount", mStepFailureCount);
            mShowingSummary = savedState.getBoolean("mShowingSummary", mShowingSummary);
            if (mShowingSummary) {
                updateViewForCompletionSummary();
            } else {
                BubblesTestStep currentTest = mTests.get(mCurrentTestIndex);
                updateViewForTest(currentTest);
                mTestStepPassed.setEnabled(savedState.getBoolean("mTestStepPassed", false));
            }
        }
    }

    private void runNextTestOrShowSummary() {
        if (mCurrentTestIndex + 1 >= mTests.size()) {
            updateViewForCompletionSummary();
        } else {
            mCurrentTestIndex++;
            BubblesTestStep currentTest = mTests.get(mCurrentTestIndex);
            updateViewForTest(currentTest);
        }
    }

    /** Populates the UI based on the provided test step */
    private void updateViewForTest(BubblesTestStep test) {
        mTestStepButtonLayout.setVisibility(VISIBLE);
        mTestTitle.setText(test.getTestTitle());
        mTestDescription.setText(test.getTestDescription());

        if (mRunnable != null) {
            mHandler.removeCallbacks(mRunnable);
        }
        if (test.waitForVerify()) {
            mTestState.setVisibility(VISIBLE);
            if (test.verify()) {
                mTestStepPassed.setEnabled(true);
                mTestState.setText(R.string.bubble_test_state_correct);
            } else {
                mTestState.setText(R.string.bubble_test_state_waiting);
                mRunnable = new Runnable() {
                    @Override
                    public void run() {
                        if (test.verify()) {
                            mTestStepPassed.setEnabled(true);
                            mTestState.setText(R.string.bubble_test_state_correct);
                        } else {
                            mHandler.postDelayed(this, 3000);
                        }
                    }
                };
                mHandler.postDelayed(mRunnable, 1000);
            }
        } else {
            mTestState.setVisibility(GONE);
        }
        if (test.getButtonText() != 0) {
            // Can't pass until test action has run
            mTestStepPassed.setEnabled(false);

            // Set up test action
            mTestAction.setOnClickListener((v) -> {
                test.performTestAction();
                mTestStepPassed.setEnabled(true);
            });
            mTestAction.setText(test.getButtonText());
            mTestAction.setVisibility(VISIBLE);
        } else {
            // No test action required
            mTestAction.setOnClickListener(null);
            mTestAction.setVisibility(INVISIBLE);
            mTestStepPassed.setEnabled(true);
        }
    }

    /** Populates the UI indicating results of test & updates test buttons as needed */
    private void updateViewForCompletionSummary() {
        mShowingSummary = true;
        // No longer need any of these buttons
        mTestStepButtonLayout.setVisibility(INVISIBLE);
        mTestAction.setVisibility(INVISIBLE);

        boolean didEverythingSucceed = mStepFailureCount == 0;
        int totalTests = mTests.size();
        int totalPasses = totalTests - mStepFailureCount;

        mTestTitle.setText(R.string.bubbles_test_summary_title);
        mTestDescription.setText(getString(R.string.bubbles_test_summary, totalPasses, totalTests));

        if (didEverythingSucceed) {
            getPassButton().setEnabled(true);
        }

        // Clean up
        ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
        shortcutManager.removeAllDynamicShortcuts();
        mNotificationManager.cancelAll();
    }

    private class CheckDefaultsTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_check_defaults_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_check_defaults_verify;
        }

        @Override
        public boolean waitForVerify() {
            return true;
        }

        @Override
        public boolean verify() {
            return mNotificationManager.getBubblePreference() == BUBBLE_PREFERENCE_NONE
                    && mNotificationManager.areBubblesEnabled();
        }
    }

    private class BubbleButtonTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_bubble_button_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_bubble_button_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_bubble_button_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            builder.setBubbleMetadata(getBubbleBuilder().build());
            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class BubblePreferenceSelected extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_app_selected_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_app_selected_verify;
        }

        @Override
        public boolean waitForVerify() {
            return true;
        }

        @Override
        public boolean verify() {
            return mNotificationManager.getBubblePreference()
                    == BUBBLE_PREFERENCE_SELECTED;
        }
    }

    private class DisableFeature extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_disable_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_disable_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_disable_button;
        }

        @Override
        public void performTestAction() {
            final Intent intent = new Intent(Settings.ACTION_NOTIFICATION_SETTINGS);
            intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent);
        }

        @Override
        public boolean waitForVerify() {
            return true;
        }

        @Override
        public boolean verify() {
            return !mNotificationManager.areBubblesEnabled();
        }
    }

    private class EnableBubblesTest extends BubblesTestStep {
        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_enable_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_enable_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_enable_button;
        }

        @Override
        public void performTestAction() {
            final String packageName = getApplicationContext().getPackageName();
            final int appUid = getApplicationInfo().uid;
            final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
            intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
            intent.putExtra(Settings.EXTRA_APP_UID, appUid);
            intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent);
        }

        @Override
        public boolean waitForVerify() {
            return true;
        }

        @Override
        public boolean verify() {
            return mNotificationManager.getBubblePreference() == BUBBLE_PREFERENCE_ALL
                    && mNotificationManager.areBubblesEnabled();
        }
    }

    private class SendBubbleTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_send_bubble_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_send_bubble_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_send_bubble_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            builder.setBubbleMetadata(getBubbleBuilder().build());

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class SuppressNotifTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_suppress_notif_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_suppress_notif_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_suppress_notif_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata = getBubbleBuilder()
                    .setSuppressNotification(true)
                    .build();
            builder.setBubbleMetadata(metadata);

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class AddNotifTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_add_notif_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_add_notif_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_add_notif_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata = getBubbleBuilder()
                    .setSuppressNotification(false)
                    .build();
            builder.setBubbleMetadata(metadata);

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class RemoveMetadataTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_remove_metadata_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_remove_metadata_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_remove_metadata_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class AddMetadataTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_add_metadata_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_add_metadata_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_add_metadata_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata = getBubbleBuilder().build();
            builder.setBubbleMetadata(metadata);

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class ExpandBubbleTest extends BubblesTestStep {
        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_expand_bubble_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_expand_bubble_verify;
        }
    }

    private class DismissBubbleTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_dismiss_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_dismiss_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_dismiss_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata = getBubbleBuilder().build();
            builder.setBubbleMetadata(metadata);

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class DismissNotificationTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_dismiss_notif_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_dismiss_notif_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_dismiss_notif_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata = getBubbleBuilder().build();
            builder.setBubbleMetadata(metadata);

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class AutoExpandBubbleTest extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_autoexpand_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_autoexpand_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_autoexpand_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata =
                    getBubbleBuilder(mShortcuts.get(0)).setAutoExpandBubble(true).build();
            builder.setBubbleMetadata(metadata);

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class CheckOverflowExists extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_overflow_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_overflow_verify;
        }
    }

    private class DismissBubbleShowsInOverflow extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_bubbles_in_overflow_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_bubbles_in_overflow_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_bubbles_in_overflow_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder =
                    getConversationNotif(getString(getTestTitle()), mShortcuts.get(0));
            builder.setBubbleMetadata(getBubbleBuilder(mShortcuts.get(0)).build());
            mNotificationManager.notify(NOTIFICATION_ID, builder.build());

            builder = getConversationNotif(getString(getTestTitle()), mShortcuts.get(1));
            builder.setBubbleMetadata(getBubbleBuilder(mShortcuts.get(1)).build());
            mNotificationManager.notify(NOTIFICATION_ID + 1, builder.build());

            builder = getConversationNotif(getString(getTestTitle()), mShortcuts.get(2));
            builder.setBubbleMetadata(getBubbleBuilder(mShortcuts.get(2)).build());
            mNotificationManager.notify(NOTIFICATION_ID + 2, builder.build());
        }
    }

    private class PromoteBubbleFromOverflow extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_add_from_overflow_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_add_from_overflow_verify;
        }
    }

    private class CancelRemovesBubblesInOverflow extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_cancel_overflow_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_cancel_overflow_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_cancel_overflow_button;
        }

        @Override
        public void performTestAction() {
            // Make sure one is a bubble
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata = getBubbleBuilder().build();
            builder.setBubbleMetadata(metadata);
            mNotificationManager.notify(NOTIFICATION_ID, builder.build());

            // Cancel the others
            mNotificationManager.cancel(NOTIFICATION_ID + 1);
            mNotificationManager.cancel(NOTIFICATION_ID + 2);
        }
    }

    private class TapNotifWithOverflowBubble extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_tap_notif_with_overflow_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_tap_notif_with_overflow_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_tap_notif_with_overflow_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            Notification.BubbleMetadata metadata = getBubbleBuilder().build();
            builder.setBubbleMetadata(metadata);
            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class PortraitAndLandscape extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_expanded_position_title;
        }

        @Override
        public int getTestDescription() {
            return mIsLargeScreen
                    ? R.string.bubbles_test_expanded_position_largescreen_verify
                    : R.string.bubbles_test_expanded_position_phone_verify;
        }
    }

    private class ScrimBehindExpandedView extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_expanded_scrim_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_expanded_scrim_verify;
        }
    }

    private class ImeInsetsExpandedView extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_ime_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_ime_verify;
        }
    }

    private class MinHeightExpandedView extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_min_height_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_min_height_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_min_height_button;
        }

        @Override
        public void performTestAction() {
            mNotificationManager.cancelAll();
            Context context = getApplicationContext();
            Intent intent = new Intent(context, BubbleActivity.class);
            intent.putExtra(EXTRA_TEST_NAME, TEST_MIN_HEIGHT);
            final PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent,
                    PendingIntent.FLAG_MUTABLE);
            Notification.BubbleMetadata.Builder b = new Notification.BubbleMetadata.Builder(
                    pendingIntent,
                    Icon.createWithResource(getApplicationContext(), R.drawable.ic_android));
            b.setDesiredHeight(0);

            Notification.Builder builder = getConversationNotif(getTestTitle());
            builder.setBubbleMetadata(b.build());
            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class MaxHeightExpandedView extends BubblesTestStep {

        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_max_height_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_max_height_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_max_height_button;
        }

        @Override
        public void performTestAction() {
            WindowMetrics windowMetrics =
                    getSystemService(WindowManager.class).getCurrentWindowMetrics();
            WindowInsets metricInsets = windowMetrics.getWindowInsets();
            Insets insets = metricInsets.getInsetsIgnoringVisibility(
                    WindowInsets.Type.navigationBars()
                            | WindowInsets.Type.statusBars()
                            | WindowInsets.Type.displayCutout());

            mNotificationManager.cancelAll();
            Context context = getApplicationContext();
            Intent intent = new Intent(context, BubbleActivity.class);
            Bundle extras = new Bundle();
            extras.putString(EXTRA_TEST_NAME, TEST_MAX_HEIGHT);
            // Pass the insets because the bubble'd activity window won't have them.
            extras.putParcelable(EXTRA_INSETS, insets);
            intent.putExtras(extras);
            final PendingIntent pendingIntent = PendingIntent.getActivity(context, 2, intent,
                    PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
            Notification.BubbleMetadata.Builder b = new Notification.BubbleMetadata.Builder(
                    pendingIntent,
                    Icon.createWithResource(getApplicationContext(), R.drawable.ic_android));
            b.setDesiredHeight(Short.MAX_VALUE);

            Notification.Builder builder = getConversationNotif(getTestTitle());
            builder.setBubbleMetadata(b.build());
            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class LowRamBubbleTest extends BubblesTestStep {
        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_lowram_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_lowram_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_lowram_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            builder.setBubbleMetadata(getBubbleBuilder().build());

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    private class BubbleDisabledTest extends BubblesTestStep {
        @Override
        public int getTestTitle() {
            return R.string.bubbles_test_disable_config_title;
        }

        @Override
        public int getTestDescription() {
            return R.string.bubbles_test_disable_config_verify;
        }

        @Override
        public int getButtonText() {
            return R.string.bubbles_test_disable_config_button;
        }

        @Override
        public void performTestAction() {
            Notification.Builder builder = getConversationNotif(getTestTitle());
            builder.setBubbleMetadata(getBubbleBuilder().build());

            mNotificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    /** Creates a shortcut to use for the notifications to be considered conversations */
    private void createShortcuts() {
        mShortcuts.clear();
        for (int i = 0; i < NUM_SHORTCUTS; i++) {
            Context context = getApplicationContext();
            Intent intent = new Intent(context, BubbleActivity.class);
            intent.setAction(ACTION_VIEW);
            intent.putExtra("CONVERSATION", i);
            String name = "BubbleBot" + i;
            Person person = new Person.Builder()
                    .setBot(false)
                    .setIcon(Icon.createWithResource(context, R.drawable.ic_android))
                    .setName(name)
                    .setImportant(true)
                    .build();
            Set<String> categorySet = new ArraySet<>();
            categorySet.add(SHORTCUT_CATEGORY);
            ShortcutInfo shortcut = new ShortcutInfo.Builder(context, name)
                    .setShortLabel(name)
                    .setLongLived(true)
                    .setPerson(person)
                    .setCategories(categorySet)
                    .setIcon(Icon.createWithResource(context, R.drawable.ic_android))
                    .setIntent(intent)
                    .build();
            mShortcuts.add(shortcut);
        }
        ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
        shortcutManager.addDynamicShortcuts(mShortcuts);
    }

    /** Creates a minimally filled out {@link android.app.Notification.BubbleMetadata.Builder} */
    private Notification.BubbleMetadata.Builder getBubbleBuilder() {
        return getBubbleBuilder(mShortcuts.get(0));
    }

    /** Creates a minimally filled out {@link android.app.Notification.BubbleMetadata.Builder} */
    private Notification.BubbleMetadata.Builder getBubbleBuilder(@Nullable ShortcutInfo info) {
        Notification.BubbleMetadata.Builder b;
        if (info == null) {
            Context context = getApplicationContext();
            Intent intent = new Intent(context, BubbleActivity.class);
            final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,
                    PendingIntent.FLAG_MUTABLE);

            b = new Notification.BubbleMetadata.Builder(pendingIntent,
                    Icon.createWithResource(getApplicationContext(),
                            R.drawable.ic_android));
        } else {
            b = new Notification.BubbleMetadata.Builder(info.getId());
        }
        b.setDesiredHeight(Short.MAX_VALUE);
        return b;
    }

    /** Creates a {@link Notification.Builder} that is a conversation. */
    private Notification.Builder getConversationNotif(int contentResId) {
        return getConversationNotif(getString(contentResId), mShortcuts.get(0));
    }

    /** Creates a {@link Notification.Builder} that is a conversation. */
    private Notification.Builder getConversationNotif(@NonNull CharSequence content,
            @NonNull ShortcutInfo shortcutInfo) {
        Context context = getApplicationContext();
        Intent intent = new Intent(context, BubbleActivity.class);
        final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,
                PendingIntent.FLAG_MUTABLE);

        Person person = new Person.Builder()
                .setName(shortcutInfo.getShortLabel())
                .build();
        RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
        PendingIntent inputIntent = PendingIntent.getActivity(getApplicationContext(), 0,
                new Intent(), PendingIntent.FLAG_MUTABLE);
        Icon icon = Icon.createWithResource(getApplicationContext(), R.drawable.ic_android);
        Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
                inputIntent).addRemoteInput(remoteInput)
                .build();

        return new Notification.Builder(context, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_android)
                .setContentTitle("Bubble Notification")
                .setContentText(content)
                .setColor(Color.GREEN)
                .setShortcutId(shortcutInfo.getId())
                .setContentIntent(pendingIntent)
                .setActions(replyAction)
                .setStyle(new Notification.MessagingStyle(person)
                        .setConversationTitle("Bubble Chat")
                        .addMessage(content,
                                SystemClock.currentThreadTimeMillis(), person)
                );
    }
}
