/*
 * 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 android.autofillservice.cts;

import static android.autofillservice.cts.activities.OutOfProcessLoginActivity.getDestroyedMarker;
import static android.autofillservice.cts.activities.OutOfProcessLoginActivity.getStartedMarker;
import static android.autofillservice.cts.activities.OutOfProcessLoginActivity.getStoppedMarker;
import static android.autofillservice.cts.testcore.Helper.ID_LOGIN;
import static android.autofillservice.cts.testcore.Helper.ID_PASSWORD;
import static android.autofillservice.cts.testcore.Helper.ID_USERNAME;
import static android.autofillservice.cts.testcore.Helper.assertTextAndValue;
import static android.autofillservice.cts.testcore.Helper.findNodeByResourceId;
import static android.autofillservice.cts.testcore.Helper.getContext;
import static android.autofillservice.cts.testcore.UiBot.LANDSCAPE;
import static android.autofillservice.cts.testcore.UiBot.PORTRAIT;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_USERNAME;

import static com.android.compatibility.common.util.ShellUtils.runShellCommand;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.assist.AssistStructure;
import android.autofillservice.cts.activities.EmptyActivity;
import android.autofillservice.cts.activities.LoginActivity;
import android.autofillservice.cts.activities.ManualAuthenticationActivity;
import android.autofillservice.cts.activities.OutOfProcessLoginActivity;
import android.autofillservice.cts.commontests.AutoFillServiceTestCase;
import android.autofillservice.cts.testcore.CannedFillResponse;
import android.autofillservice.cts.testcore.Helper;
import android.autofillservice.cts.testcore.InstrumentedAutoFillService;
import android.autofillservice.cts.testcore.Timeouts;
import android.autofillservice.cts.testcore.UiBot;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
import android.support.test.uiautomator.UiObject2;
import android.util.Log;
import android.view.autofill.AutofillValue;

import com.android.compatibility.common.util.Timeout;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.Callable;

/**
 * Test the lifecycle of a autofill session
 */
@AppModeFull(reason = "This test requires android.permission.WRITE_EXTERNAL_STORAGE")
public class SessionLifecycleTest extends AutoFillServiceTestCase.ManualActivityLaunch {
    private static final String TAG = "SessionLifecycleTest";

    private static final String ID_BUTTON = "button";
    private static final String ID_CANCEL = "cancel";

    /**
     * Delay for activity start/stop.
     */
    // TODO: figure out a better way to wait without using sleep().
    private static final long WAIT_ACTIVITY_MS = 1000;

    private static final Timeout SESSION_LIFECYCLE_TIMEOUT = new Timeout(
            "SESSION_LIFECYCLE_TIMEOUT", 5000, 2F, 5000);

    /**
     * Runs an {@code assertion}, retrying until {@code timeout} is reached.
     */
    private static void eventually(String description, Callable<Boolean> assertion)
            throws Exception {
        SESSION_LIFECYCLE_TIMEOUT.run(description, assertion);
    }

    public SessionLifecycleTest() {
        super(new UiBot(SESSION_LIFECYCLE_TIMEOUT));
    }

    /**
     * Prevents the screen to rotate by itself
     */
    @Before
    public void disableAutoRotation() throws Exception {
        Helper.disableAutoRotation(mUiBot);
    }

    /**
     * Allows the screen to rotate by itself
     */
    @After
    public void allowAutoRotation() {
        Helper.allowAutoRotation();
    }

    @After
    public void finishLoginActivityOnAnotherProcess() throws Exception {
        runShellCommand(
                "am broadcast --receiver-foreground -n android.autofillservice.cts/.testcore"
                        + ".OutOfProcessLoginActivityFinisherReceiver");
        mUiBot.assertGoneByRelativeId(ID_USERNAME, Timeouts.ACTIVITY_RESURRECTION);

        if (!OutOfProcessLoginActivity.hasInstance()) {
            Log.v(TAG, "@After: Not waiting for oop activity to be destroyed");
            return;
        }
        // Waiting for activity to be destroyed (destroy marker appears)
        eventually("getDestroyedMarker()", () -> {
            return getDestroyedMarker(getContext()).exists();
        });
    }

    private void killOfProcessLoginActivityProcess() throws Exception {
        // Waiting for activity to stop (stop marker appears)
        eventually("getStoppedMarker()", () -> {
            return getStoppedMarker(getContext()).exists();
        });

        // onStop might not be finished, hence wait more
        SystemClock.sleep(WAIT_ACTIVITY_MS);

        // Kill activity that is in the background
        runShellCommand("am broadcast --receiver-foreground "
                + "-n android.autofillservice.cts/.testcore.SelfDestructReceiver");
    }

    private void startAndWaitExternalActivity() throws Exception {
        final Intent outOfProcessAcvitityStartIntent = new Intent(getContext(),
                OutOfProcessLoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getStartedMarker(getContext()).delete();
        getContext().startActivity(outOfProcessAcvitityStartIntent);
        eventually("getStartedMarker()", () -> {
            return getStartedMarker(getContext()).exists();
        });
        getStartedMarker(getContext()).delete();
        // Even if we wait the activity started, UiObject still fails. Have to wait a little bit.
        SystemClock.sleep(WAIT_ACTIVITY_MS);

        mUiBot.assertShownByRelativeId(ID_USERNAME);
    }

    @Test
    public void testDatasetAuthResponseWhileAutofilledAppIsLifecycled() throws Exception {
        assumeTrue("Rotation is supported", Helper.isRotationSupported(mContext));
        final ActivityManager activityManager = (ActivityManager) getContext()
                .getSystemService(Context.ACTIVITY_SERVICE);
        assumeFalse(activityManager.isLowRamDevice());

        // Set service.
        enableService();

        try {

            // Start activity that is autofilled in a separate process so it can be killed
            startAndWaitExternalActivity();

            // Set expectations.
            final Bundle extras = new Bundle();
            extras.putString("numbers", "4815162342");

            // Create the authentication intent (launching a full screen activity)
            IntentSender authentication = PendingIntent.getActivity(getContext(), 0,
                    new Intent(getContext(), ManualAuthenticationActivity.class),
                    PendingIntent.FLAG_MUTABLE).getIntentSender();

            // Prepare the authenticated response
            ManualAuthenticationActivity.setResponse(new CannedFillResponse.Builder()
                    .addDataset(new CannedFillResponse.CannedDataset.Builder()
                            .setField(ID_USERNAME, AutofillValue.forText("autofilled username"))
                            .setPresentation(createPresentation("dataset")).build())
                    .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                    .setExtras(extras).build());

            CannedFillResponse response = new CannedFillResponse.Builder()
                    .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                    .setPresentation(createPresentation("authenticate"))
                    .build();
            sReplier.addResponse(response);

            // Trigger autofill on username
            mUiBot.selectByRelativeId(ID_USERNAME);

            // Wait for fill request to be processed
            sReplier.getNextFillRequest();

            // Wait until authentication is shown
            mUiBot.assertDatasets("authenticate");

            // Change orientation which triggers a destroy -> create in the app as the activity
            // cannot deal with such situations
            mUiBot.setScreenOrientation(LANDSCAPE);
            mUiBot.setScreenOrientation(PORTRAIT);

            // Wait context and Views being recreated in rotation
            mUiBot.assertShownByRelativeId(ID_USERNAME);

            // Delete stopped marker
            getStoppedMarker(getContext()).delete();

            // Authenticate
            mUiBot.selectDataset("authenticate");

            // Kill activity that is in the background
            killOfProcessLoginActivityProcess();

            // Change orientation which triggers a destroy -> create in the app as the activity
            // cannot deal with such situations
            mUiBot.setScreenOrientation(PORTRAIT);

            // Approve authentication
            mUiBot.selectByRelativeId(ID_BUTTON);

            // Wait for dataset to be shown
            mUiBot.assertDatasets("dataset");

            // Change orientation which triggers a destroy -> create in the app as the activity
            // cannot deal with such situations
            mUiBot.setScreenOrientation(LANDSCAPE);

            // Select dataset
            mUiBot.selectDataset("dataset");

            // Check the results.
            eventually("getTextById(" + ID_USERNAME + ")", () -> {
                return mUiBot.getTextByRelativeId(ID_USERNAME).equals("autofilled username");
            });

            // Set password
            mUiBot.setTextByRelativeId(ID_PASSWORD, "new password");

            // Login
            mUiBot.selectByRelativeId(ID_LOGIN);

            // Wait for save UI to be shown
            mUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);

            // Change orientation to make sure save UI can handle this
            mUiBot.setScreenOrientation(PORTRAIT);

            // Tap "Save".
            mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

            // Get save request
            InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
            assertWithMessage("onSave() not called").that(saveRequest).isNotNull();

            // Make sure data is correctly saved
            final AssistStructure.ViewNode username = findNodeByResourceId(saveRequest.structure,
                    ID_USERNAME);
            assertTextAndValue(username, "autofilled username");
            final AssistStructure.ViewNode password = findNodeByResourceId(saveRequest.structure,
                    ID_PASSWORD);
            assertTextAndValue(password, "new password");

            // Make sure extras were passed back on onSave()
            assertThat(saveRequest.data).isNotNull();
            final String extraValue = saveRequest.data.getString("numbers");
            assertWithMessage("extras not passed on save").that(extraValue).isEqualTo("4815162342");
        } finally {
            mUiBot.resetScreenResolution();
        }
    }

    @Test
    public void testAuthCanceledWhileAutofilledAppIsLifecycled() throws Exception {
        // Set service.
        enableService();

        // Start activity that is autofilled in a separate process so it can be killed
        startAndWaitExternalActivity();

        // Create the authentication intent (launching a full screen activity)
        IntentSender authentication = PendingIntent.getActivity(getContext(), 0,
                new Intent(getContext(), ManualAuthenticationActivity.class),
                PendingIntent.FLAG_IMMUTABLE).getIntentSender();

        CannedFillResponse response = new CannedFillResponse.Builder()
                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                .setPresentation(createPresentation("authenticate"))
                .build();
        sReplier.addResponse(response);

        // Trigger autofill on username
        mUiBot.selectByRelativeId(ID_USERNAME);

        // Wait for fill request to be processed
        sReplier.getNextFillRequest();

        // Wait until authentication is shown
        mUiBot.assertDatasets("authenticate");

        // Delete stopped marker
        getStoppedMarker(getContext()).delete();

        // Authenticate
        mUiBot.selectDataset("authenticate");

        // Kill activity that is in the background
        killOfProcessLoginActivityProcess();

        // Set expectations.
        sReplier.addResponse(
                new CannedFillResponse.Builder()
                        .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                        .setPresentation(createPresentation("authenticate2"))
                        .build());

        // Cancel authentication activity
        mUiBot.pressBack();

        // Wait for fill request to be processed
        mUiBot.waitForIdle();
        sReplier.getNextFillRequest();

        // Authentication should still be shown
        mUiBot.assertDatasets("authenticate2");
    }

    @Test
    public void testDatasetVisibleWhileAutofilledAppIsLifecycled() throws Exception {
        // Set service.
        enableService();

        // Start activity that is autofilled in a separate process so it can be killed
        startAndWaitExternalActivity();

        CannedFillResponse response = new CannedFillResponse.Builder()
                .addDataset(new CannedFillResponse.CannedDataset.Builder(
                        createPresentation("dataset"))
                                .setField(ID_USERNAME, "filled").build())
                .build();
        sReplier.addResponse(response);

        // Trigger autofill on username
        mUiBot.selectByRelativeId(ID_USERNAME);

        // Wait for fill request to be processed
        sReplier.getNextFillRequest();

        // Wait until dataset is shown
        mUiBot.assertDatasets("dataset");

        // Delete stopped marker
        getStoppedMarker(getContext()).delete();

        // Start an activity on top of the autofilled activity
        Intent intent = new Intent(getContext(), EmptyActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        getContext().startActivity(intent);

        // Kill activity that is in the background
        killOfProcessLoginActivityProcess();

        // Add response for back to the first activity
        sReplier.addResponse(
                new CannedFillResponse.Builder()
                        .addDataset(new CannedFillResponse.CannedDataset.Builder(
                                createPresentation("dataset2"))
                                        .setField(ID_USERNAME, "filled").build())
                        .build());

        // Cancel activity on top
        mUiBot.pressBack();

        // Wait for fill request to be processed
        mUiBot.waitForIdle();
        sReplier.getNextFillRequest();

        // Dataset should still be shown
        mUiBot.assertDatasets("dataset2");
    }

    @Test
    public void testAutofillNestedActivitiesWhileAutofilledAppIsLifecycled() throws Exception {
        // Set service.
        enableService();

        // Start activity that is autofilled in a separate process so it can be killed
        startAndWaitExternalActivity();

        // Prepare response for first activity
        CannedFillResponse response = new CannedFillResponse.Builder()
                .addDataset(new CannedFillResponse.CannedDataset.Builder(
                        createPresentation("dataset1"))
                                .setField(ID_USERNAME, "filled").build())
                .build();
        sReplier.addResponse(response);

        // Trigger autofill on username
        mUiBot.selectByRelativeId(ID_USERNAME);

        // Wait for fill request to be processed
        sReplier.getNextFillRequest();

        // Wait until dataset1 is shown
        mUiBot.assertDatasets("dataset1");

        // Delete stopped marker
        getStoppedMarker(getContext()).delete();

        // Prepare response for nested activity
        response = new CannedFillResponse.Builder()
                .addDataset(new CannedFillResponse.CannedDataset.Builder(
                        createPresentation("dataset2"))
                                .setField(ID_USERNAME, "filled").build())
                .build();
        sReplier.addResponse(response);

        // Start nested login activity
        Intent intent = new Intent(getContext(), LoginActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        getContext().startActivity(intent);

        // Kill activity that is in the background
        killOfProcessLoginActivityProcess();

        // Trigger autofill on username in nested activity
        mUiBot.selectByRelativeId(ID_USERNAME);

        // Wait for fill request to be processed
        sReplier.getNextFillRequest();

        // Wait until dataset in nested activity is shown
        mUiBot.assertDatasets("dataset2");

        // Set expectations for back to the first activity
        sReplier.addResponse(
                new CannedFillResponse.Builder()
                        .addDataset(new CannedFillResponse.CannedDataset.Builder(
                                createPresentation("dataset3"))
                                        .setField(ID_USERNAME, "filled").build())
                        .build());

        // Tap "Cancel".
        mUiBot.selectByRelativeId(ID_CANCEL);

        // Wait for fill request to be processed
        mUiBot.waitForIdle();
        sReplier.getNextFillRequest();

        // Dataset should still be shown
        mUiBot.assertDatasets("dataset3");
    }

    @Test
    public void testDatasetGoesAwayWhenAutofilledAppIsKilled() throws Exception {
        // Set service.
        enableService();

        // Start activity that is autofilled in a separate process so it can be killed
        startAndWaitExternalActivity();

        final CannedFillResponse response = new CannedFillResponse.Builder()
                .addDataset(new CannedFillResponse.CannedDataset.Builder(
                        createPresentation("dataset"))
                                .setField(ID_USERNAME, "filled").build())
                .build();
        sReplier.addResponse(response);

        // Trigger autofill on username
        mUiBot.selectByRelativeId(ID_USERNAME);

        // Wait for fill request to be processed
        sReplier.getNextFillRequest();

        // Wait until dataset is shown
        mUiBot.assertDatasets("dataset");

        // Kill activity
        killOfProcessLoginActivityProcess();

        // Make sure dataset is not shown anymore
        mUiBot.assertNoDatasetsEver();

        // Restart activity an make sure the dataset is still not shown
        startAndWaitExternalActivity();
        mUiBot.assertNoDatasets();
    }

    @Test
    public void testSaveRemainsWhenAutofilledAppIsKilled() throws Exception {
        // Set service.
        enableService();

        // Start activity that is autofilled in a separate process so it can be killed
        startAndWaitExternalActivity();

        final CannedFillResponse response = new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_USERNAME, ID_USERNAME)
                .build();
        sReplier.addResponse(response);

        // Trigger autofill on username
        mUiBot.selectByRelativeId(ID_USERNAME);

        // Wait for fill request to be processed
        sReplier.getNextFillRequest();

        // Wait until dataset is shown
        mUiBot.assertNoDatasetsEver();

        // Trigger save
        mUiBot.setTextByRelativeId(ID_USERNAME, "dude");
        mUiBot.selectByRelativeId(ID_LOGIN);
        mUiBot.assertSaveShowing(SAVE_DATA_TYPE_USERNAME);

        // Kill activity
        killOfProcessLoginActivityProcess();

        // Make sure save is still showing
        final UiObject2 saveSnackBar = mUiBot.assertSaveShowing(SAVE_DATA_TYPE_USERNAME);

        mUiBot.saveForAutofill(saveSnackBar, true);

        final InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();

        // Make sure data is correctly saved
        final AssistStructure.ViewNode username = findNodeByResourceId(saveRequest.structure,
                ID_USERNAME);
        assertTextAndValue(username, "dude");
    }
}