/*
 * Copyright (C) 2021 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.server.wm.jetpack;

import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.DEFAULT_SPLIT_RATIO;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.UNEVEN_CONTAINERS_DEFAULT_SPLIT_RATIO;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.assertValidSplit;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplit;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitAndAssertNotVisible;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.waitForFillsTask;

import static org.junit.Assert.assertTrue;

import android.app.Activity;
import android.content.Intent;
import android.server.wm.jetpack.utils.TestActivity;
import android.server.wm.jetpack.utils.TestActivityWithId;
import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
import android.util.LayoutDirection;
import android.util.Pair;
import android.util.Size;

import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.window.extensions.embedding.SplitPairRule;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Collections;
import java.util.Set;

/**
 * Tests for the {@link androidx.window.extensions} implementation provided on the device (and only
 * if one is available) for the Activity Embedding functionality. Specifically tests activity
 * split bounds.
 *
 * Build/Install/Run:
 *     atest CtsWindowManagerJetpackTestCases:ActivityEmbeddingBoundsTests
 */
@RunWith(AndroidJUnit4.class)
public class ActivityEmbeddingBoundsTests extends ActivityEmbeddingTestBase {

    /**
     * Tests that when two activities are in a split and the parent bounds shrink such that
     * they can no longer support split activities, then the activities become stacked.
     */
    @Test
    public void testParentWindowMetricsPredicate() {
        // Launch primary activity
        final Activity primaryActivity = startActivityNewTask(
                TestConfigChangeHandlingActivity.class);

        // Set split pair rule such that if the parent width is any smaller than it is now, then
        // the parent cannot support a split.
        final int originalTaskWidth = getTaskWidth();
        final SplitPairRule splitPairRule = new SplitPairRule.Builder(
                activityActivityPair -> true /* activityPairPredicate */,
                activityIntentPair -> true /* activityIntentPredicate */,
                parentWindowMetrics -> parentWindowMetrics.getBounds().width() >= originalTaskWidth)
                .setSplitRatio(DEFAULT_SPLIT_RATIO).build();
        mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));

        // Launch the secondary activity
        final String secondaryActivityId = "secondaryActivityId";
        final TestActivity secondaryActivity = (TestActivity) startActivityAndVerifySplit(
                primaryActivity, TestActivityWithId.class, splitPairRule, secondaryActivityId,
                mSplitInfoConsumer);

        // Resize the display multiple times to verify that the activities are correctly split or
        // stacked depending on the parent bounds. Resizing multiple times simulates a foldable
        // display is that folded and unfolded multiple times while running the same app.
        final int numTimesToResize = 2;
        final Size originalDisplaySize = mReportedDisplayMetrics.getSize();
        for (int i = 0; i < numTimesToResize; i++) {
            // Shrink the display by 10% to make the activities stacked
            mReportedDisplayMetrics.setSize(new Size((int) (originalDisplaySize.getWidth() * 0.9),
                    originalDisplaySize.getHeight()));
            waitForFillsTask(secondaryActivity);
            waitAndAssertNotVisible(primaryActivity);

            // Return the display to its original size and verify that the activities are split
            secondaryActivity.resetBoundsChangeCounter();
            mReportedDisplayMetrics.setSize(originalDisplaySize);
            assertTrue(secondaryActivity.waitForBoundsChange());
            assertValidSplit(primaryActivity, secondaryActivity, splitPairRule);
        }
    }

    /**
     * Tests that the activity bounds for activities in a split match the LTR layout direction
     * provided in the {@link SplitPairRule}.
     */
    @Test
    public void testLayoutDirection_LTR() {
        // Create a split pair rule with layout direction LTR and a split ratio that results in
        // uneven bounds between the primary and secondary containers.
        final SplitPairRule splitPairRule = createUnevenWidthSplitPairRule(LayoutDirection.LTR);
        mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));

        // Start activities in a split and verify that the layout direction is LTR, which is
        // checked in {@link ActivityEmbeddingUtil#startActivityAndVerifySplit}.
        Activity primaryActivity = startActivityNewTask(TestConfigChangeHandlingActivity.class);
        startActivityAndVerifySplit(primaryActivity, TestActivityWithId.class, splitPairRule,
                "secondaryActivityId", mSplitInfoConsumer);
    }

    /**
     * Tests that the activity bounds for activities in a split match the RTL layout direction
     * provided in the {@link SplitPairRule}.
     */
    @Test
    public void testLayoutDirection_RTL() {
        // Create a split pair rule with layout direction RTL and a split ratio that results in
        // uneven bounds between the primary and secondary containers.
        final SplitPairRule splitPairRule = createUnevenWidthSplitPairRule(LayoutDirection.RTL);
        mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));

        // Start activities in a split and verify that the layout direction is RTL, which is
        // checked in {@link ActivityEmbeddingUtil#startActivityAndVerifySplit}.
        Activity primaryActivity = startActivityNewTask(TestConfigChangeHandlingActivity.class);
        startActivityAndVerifySplit(primaryActivity, TestActivityWithId.class, splitPairRule,
                "secondaryActivityId", mSplitInfoConsumer);
    }

    /**
     * Tests that the activity bounds for activities in a split match the Locale layout direction
     * provided in the {@link SplitPairRule}.
     */
    @Test
    public void testLayoutDirection_Locale() {
        // Create a split pair rule with layout direction LOCALE and a split ratio that results in
        // uneven bounds between the primary and secondary containers.
        final SplitPairRule splitPairRule = createUnevenWidthSplitPairRule(LayoutDirection.LOCALE);
        mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));

        // Start activities in a split and verify that the layout direction is the device locale,
        // which is checked in {@link ActivityEmbeddingUtil#startActivityAndVerifySplit}.
        Activity primaryActivity = startActivityNewTask(TestConfigChangeHandlingActivity.class);
        startActivityAndVerifySplit(primaryActivity, TestActivityWithId.class, splitPairRule,
                "secondaryActivityId", mSplitInfoConsumer);
    }

    /**
     * Tests that when two activities enter a split, then their split ratio matches what is in their
     * {@link SplitPairRule}, and is not assumed to be 0.5 or match the split ratio of the previous
     * top-most activity split.
     */
    @Test
    public void testSplitRatio() {
        final String activityAId = "activityA";
        final String activityBId = "activityB";
        final String activityCId = "activityC";
        final float activityABSplitRatio = 0.37f;
        final float activityBCSplitRatio = 0.85f;

        // Create a split rule for activity A and activity B where the split ratio is 0.37.
        final SplitPairRule splitPairRuleAB = new SplitPairRule.Builder(
                activityActivityPair -> false /* activityPairPredicate */,
                activityIntentPair -> matchesActivityIntentPair(activityIntentPair, activityAId,
                        activityBId) /* activityIntentPredicate */,
                parentWindowMetrics -> true /* parentWindowMetricsPredicate */)
                .setSplitRatio(activityABSplitRatio).build();

        // Create a split rule for activity B and activity C where the split ratio is 0.65.
        final SplitPairRule splitPairRuleBC = new SplitPairRule.Builder(
                activityActivityPair -> false /* activityPairPredicate */,
                activityIntentPair -> matchesActivityIntentPair(activityIntentPair, activityBId,
                        activityCId) /* activityIntentPredicate */,
                parentWindowMetrics -> true /* parentWindowMetricsPredicate */)
                .setSplitRatio(activityBCSplitRatio).build();

        // Register the two split pair rules
        mActivityEmbeddingComponent.setEmbeddingRules(Set.of(splitPairRuleAB, splitPairRuleBC));

        // Launch the activity A and B split and verify that the split ratio is 0.37 in
        // {@link ActivityEmbeddingUtil#startActivityAndVerifySplit}.
        Activity activityA = startActivityNewTask(TestActivityWithId.class, activityAId);
        Activity activityB = startActivityAndVerifySplit(activityA, TestActivityWithId.class,
                splitPairRuleAB, activityBId, mSplitInfoConsumer);

        // Launch the activity B and C split and verify that the split ratio is 0.65 in
        // {@link ActivityEmbeddingUtil#startActivityAndVerifySplit}.
        Activity activityC = startActivityAndVerifySplit(activityB, TestActivityWithId.class,
                splitPairRuleBC, activityCId, mSplitInfoConsumer);

        // Finish activity C so that activity A and B are in a split again. Verify that the split
        // ratio returns to 0.37 in {@link ActivityEmbeddingUtil#assertValidSplit}.
        activityC.finish();
        assertValidSplit(activityA, activityB, splitPairRuleAB);
    }

    private SplitPairRule createUnevenWidthSplitPairRule(int layoutDir) {
        return new SplitPairRule.Builder(activityActivityPair -> true /* activityPairPredicate */,
                activityIntentPair -> true /* activityIntentPredicate */,
                parentWindowMetrics -> true /* parentWindowMetricsPredicate */)
                .setSplitRatio(UNEVEN_CONTAINERS_DEFAULT_SPLIT_RATIO)
                .setLayoutDirection(layoutDir).build();
    }

    private boolean matchesActivityIntentPair(@NonNull Pair<Activity, Intent> activityIntentPair,
            @NonNull String primaryActivityId, @NonNull String secondaryActivityId) {
        if (!(activityIntentPair.first instanceof TestActivityWithId)) {
            return false;
        }
        return primaryActivityId.equals(((TestActivityWithId) activityIntentPair.first).getId())
                && secondaryActivityId.equals(activityIntentPair.second.getStringExtra(
                        ACTIVITY_ID_LABEL));
    }
}
