/*
 * Copyright (C) 2015 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.cts;

import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.log.LogUtil.CLog;

import java.awt.Rectangle;

public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {

    private static final String TEST_ACTIVITY_NAME = "TestActivity";
    private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
    private static final String DOCKED_ACTIVITY_NAME = "DockedActivity";
    private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
    private static final String SINGLE_INSTANCE_ACTIVITY_NAME = "SingleInstanceActivity";
    private static final String SINGLE_TASK_ACTIVITY_NAME = "SingleTaskActivity";

    private static final int TASK_SIZE = 600;
    private static final int STACK_SIZE = 300;

    public void testStackList() throws Exception {
        if (!supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
            return;
        }

        executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
        mAmWmState.assertContainsStack(
                "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
        mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
    }

    public void testDockActivity() throws Exception {
        if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
            return;
        }

        launchActivityInDockStack(TEST_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
        mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
    }

    public void testNonResizeableNotDocked() throws Exception {
        if (!supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
            return;
        }

        launchActivityInDockStack(NON_RESIZEABLE_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});

        mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
        mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
        mAmWmState.assertFrontStack(
                "Fullscreen stack must be front stack.", FULLSCREEN_WORKSPACE_STACK_ID);
    }

    public void testLaunchToSide() throws Exception {
        if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
            return;
        }

        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
        launchActivityToSide();
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        mAmWmState.assertContainsStack(
                "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
        mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
    }

    public void testLaunchToSideAndBringToFront() throws Exception {
        if (!supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
            return;
        }

        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        final String[] waitForFirstVisible = new String[] {TEST_ACTIVITY_NAME};
        final String[] waitForSecondVisible = new String[] {NO_RELAUNCH_ACTIVITY_NAME};
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        // Launch activity to side.
        launchActivityToSide();
        mAmWmState.computeState(mDevice, waitForFirstVisible);
        int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                TEST_ACTIVITY_NAME);

        // Launch another activity to side to cover first one.
        launchActivityInStack(NO_RELAUNCH_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
        mAmWmState.computeState(mDevice, waitForSecondVisible);
        int taskNumberCovered = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertEquals("Fullscreen stack must have one task added.",
                taskNumberInitial + 1, taskNumberCovered);
        mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
                NO_RELAUNCH_ACTIVITY_NAME);

        // Launch activity that was first launched to side. It should be brought to front.
        launchActivityToSide();
        mAmWmState.computeState(mDevice, waitForFirstVisible);
        int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertEquals("Task number in fullscreen stack must remain the same.",
                taskNumberCovered, taskNumberFinal);
        mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
                TEST_ACTIVITY_NAME);
    }

    public void testLaunchToSideMultiple() throws Exception {
        if (!supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
            return;
        }

        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
        final String[] waitForActivitiesVisible =
            new String[] {TEST_ACTIVITY_NAME, LAUNCHING_ACTIVITY};

        // Launch activity to side.
        launchActivityToSide();
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
                mAmWmState.getAmState()
                        .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));

        // Try to launch to side same activity again.
        launchActivityToSide();
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
        mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
                TEST_ACTIVITY_NAME);
        mAmWmState.assertNotNull("Launched to side activity must remain in fullscreen stack.",
                mAmWmState.getAmState()
                        .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
    }

    public void testLaunchToSideSingleInstance() throws Exception {
        launchTargetToSide(SINGLE_INSTANCE_ACTIVITY_NAME, false);
    }

    public void testLaunchToSideSingleTask() throws Exception {
        launchTargetToSide(SINGLE_TASK_ACTIVITY_NAME, false);
    }

    public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
        launchTargetToSide(TEST_ACTIVITY_NAME, true);
    }

    private void launchTargetToSide(String targetActivityName,
                                    boolean taskCountMustIncrement) throws Exception {
        if (!supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
            return;
        }

        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});

        final String[] waitForActivitiesVisible =
            new String[] {targetActivityName, LAUNCHING_ACTIVITY};

        // Launch activity to side with data.
        launchActivityToSide(true, false, targetActivityName);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        mAmWmState.assertContainsStack(
                "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
        int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
                mAmWmState.getAmState()
                        .getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));

        // Try to launch to side same activity again with different data.
        launchActivityToSide(true, false, targetActivityName);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        int taskNumberSecondLaunch = mAmWmState.getAmState()
                .getStackById(FULLSCREEN_WORKSPACE_STACK_ID).getTasks().size();
        if (taskCountMustIncrement) {
            mAmWmState.assertEquals("Task number must be incremented.", taskNumberInitial + 1,
                    taskNumberSecondLaunch);
        } else {
            mAmWmState.assertEquals("Task number must not change.", taskNumberInitial,
                    taskNumberSecondLaunch);
        }
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                targetActivityName);
        mAmWmState.assertNotNull("Launched to side activity must be launched in fullscreen stack.",
                mAmWmState.getAmState()
                        .getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));

        // Try to launch to side same activity again with no data.
        launchActivityToSide(false, false, targetActivityName);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        if (taskCountMustIncrement) {
            mAmWmState.assertEquals("Task number must be incremented.", taskNumberSecondLaunch + 1,
                    taskNumberFinal);
        } else {
            mAmWmState.assertEquals("Task number must not change.", taskNumberSecondLaunch,
                    taskNumberFinal);
        }
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                targetActivityName);
        mAmWmState.assertNotNull("Launched to side activity must be launched in fullscreen stack.",
                mAmWmState.getAmState()
                        .getTaskByActivityName(targetActivityName, FULLSCREEN_WORKSPACE_STACK_ID));
    }

    public void testLaunchToSideMultipleWithFlag() throws Exception {
        if (!supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
            return;
        }

        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
        final String[] waitForActivitiesVisible =
            new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};

        // Launch activity to side.
        launchActivityToSide();
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
                mAmWmState.getAmState()
                        .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));

        // Try to launch to side same activity again, but with Intent#FLAG_ACTIVITY_MULTIPLE_TASK.
        launchActivityToSide(false, true);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
                .getTasks().size();
        mAmWmState.assertEquals("Task number must be incremented.", taskNumberInitial + 1,
                taskNumberFinal);
        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                TEST_ACTIVITY_NAME);
        mAmWmState.assertNotNull("Launched to side activity must remain in fullscreen stack.",
                mAmWmState.getAmState()
                        .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
    }

    public void testRotationWhenDocked() throws Exception {
        if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
            return;
        }

        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
        launchActivityToSide();
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        mAmWmState.assertContainsStack(
                "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
        mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);

        // Rotate device single steps (90°) 0-1-2-3.
        // Each time we compute the state we implicitly assert valid bounds.
        String[] waitForActivitiesVisible =
            new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
        setDeviceRotation(0);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        setDeviceRotation(1);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        setDeviceRotation(2);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        setDeviceRotation(3);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for double
        // step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
        setDeviceRotation(1);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        setDeviceRotation(3);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        setDeviceRotation(0);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        setDeviceRotation(2);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
        setDeviceRotation(0);
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    }

    public void testRotationWhenDockedWhileLocked() throws Exception {
        if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow())  {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
            return;
        }

        launchActivityInDockStack(LAUNCHING_ACTIVITY);
        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
        launchActivityToSide();
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        mAmWmState.assertSanity();
        mAmWmState.assertContainsStack(
                "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
        mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);

        String[] waitForActivitiesVisible =
            new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
        lockDevice();
        setDeviceRotation(0);
        unlockDevice();
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);

        lockDevice();
        setDeviceRotation(1);
        unlockDevice();
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);

        lockDevice();
        setDeviceRotation(2);
        unlockDevice();
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);

        lockDevice();
        setDeviceRotation(3);
        unlockDevice();
        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
    }

    public void testResizeDockedStack() throws Exception {
        if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
            return;
        }

        launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
        launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
        resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME, DOCKED_ACTIVITY_NAME},
                false /* compareTaskAndStackBounds */);
        mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
        mAmWmState.assertContainsStack("Must contain fullscreen stack",
                FULLSCREEN_WORKSPACE_STACK_ID);
        assertEquals(new Rectangle(0, 0, STACK_SIZE, STACK_SIZE),
                mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds());
        mAmWmState.assertDockedTaskBounds(TASK_SIZE, DOCKED_ACTIVITY_NAME);
        mAmWmState.assertVisibility(DOCKED_ACTIVITY_NAME, true);
        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true);
    }

    public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
        if (!supportsMultiWindowMode() || !supportsSplitScreenMultiWindow()) {
            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
            return;
        }
        final String[] waitTestActivityName = new String[] {TEST_ACTIVITY_NAME};
        executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
        mAmWmState.computeState(mDevice, waitTestActivityName);
        final Rectangle fullScreenBounds =
                mAmWmState.getWmState().getStack(FULLSCREEN_WORKSPACE_STACK_ID).getBounds();

        moveActivityToDockStack(TEST_ACTIVITY_NAME);
        mAmWmState.computeState(mDevice, waitTestActivityName);
        launchActivityInStack(NO_RELAUNCH_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);

        mAmWmState.computeState(mDevice,
                new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
        final Rectangle initialDockBounds =
                mAmWmState.getWmState().getStack(DOCKED_STACK_ID).getBounds();

        clearLogcat();

        Rectangle newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, true);
        resizeDockedStack(newBounds.width, newBounds.height, newBounds.width, newBounds.height);
        mAmWmState.computeState(mDevice,
                new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});

        // We resize twice to make sure we cross an orientation change threshold for both
        // activities.
        newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, false);
        resizeDockedStack(newBounds.width, newBounds.height, newBounds.width, newBounds.height);
        mAmWmState.computeState(mDevice,
                new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
        assertActivityLifecycle(TEST_ACTIVITY_NAME, true);
        assertActivityLifecycle(NO_RELAUNCH_ACTIVITY_NAME, false);
    }

    private Rectangle computeNewDockBounds(
            Rectangle fullscreenBounds, Rectangle dockBounds, boolean reduceSize) {
        final boolean inLandscape = fullscreenBounds.width > dockBounds.width;
        // We are either increasing size or reducing it.
        final float sizeChangeFactor = reduceSize ? 0.5f : 1.5f;
        final Rectangle newBounds = new Rectangle(dockBounds);
        if (inLandscape) {
            // In landscape we change the width.
            newBounds.width *= sizeChangeFactor;
        } else {
            // In portrait we change the height
            newBounds.height *= sizeChangeFactor;
        }

        return newBounds;
    }

    private void launchActivityToSide() throws Exception {
        launchActivityToSide(false, false);
    }

    private void launchActivityToSide(boolean randomData, boolean multipleTaskFlag)
            throws Exception {
        launchActivityToSide(randomData, multipleTaskFlag, null);
    }
}
