/*
 * 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 android.server.wm;

import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.provider.Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS;
import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_90;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import android.app.Activity;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.graphics.Insets;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.server.wm.settings.SettingsSession;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager.LayoutParams;

import androidx.test.rule.ActivityTestRule;

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

import org.hamcrest.CustomTypeSafeMatcher;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;

import java.util.function.Supplier;

@Presubmit
public class WindowInsetsPolicyTest extends ActivityManagerTestBase {
    private static final String TAG = WindowInsetsPolicyTest.class.getSimpleName();

    private ComponentName mTestActivityComponentName;

    private SettingsSession<String> mImmersiveModeConfirmationSetting;

    @Rule
    public final ErrorCollector mErrorCollector = new ErrorCollector();

    @Rule
    public final ActivityTestRule<TestActivity> mTestActivity =
            new ActivityTestRule<>(TestActivity.class, false /* initialTouchMode */,
                    false /* launchActivity */);

    @Rule
    public final ActivityTestRule<FullscreenTestActivity> mFullscreenTestActivity =
            new ActivityTestRule<>(FullscreenTestActivity.class, false /* initialTouchMode */,
                    false /* launchActivity */);

    @Rule
    public final ActivityTestRule<FullscreenWmFlagsTestActivity> mFullscreenWmFlagsTestActivity =
            new ActivityTestRule<>(FullscreenWmFlagsTestActivity.class,
                    false /* initialTouchMode */, false /* launchActivity */);

    @Rule
    public final ActivityTestRule<ImmersiveFullscreenTestActivity> mImmersiveTestActivity =
            new ActivityTestRule<>(ImmersiveFullscreenTestActivity.class,
                    false /* initialTouchMode */, false /* launchActivity */);

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
        mTestActivityComponentName = new ComponentName(mContext, TestActivity.class);
        mImmersiveModeConfirmationSetting = new SettingsSession<>(
                Settings.Secure.getUriFor(IMMERSIVE_MODE_CONFIRMATIONS),
                Settings.Secure::getString, Settings.Secure::putString);
        mImmersiveModeConfirmationSetting.set("confirmed");

    }

    @After
    public void tearDown() {
        if (mImmersiveModeConfirmationSetting != null) {
            mImmersiveModeConfirmationSetting.close();
        }
    }

    @Test
    public void testWindowInsets_dispatched() {
        final TestActivity activity = launchAndWait(mTestActivity);

        WindowInsets insets = getOnMainSync(activity::getDispatchedInsets);
        Assert.assertThat("test setup failed, no insets dispatched", insets, notNullValue());

        commonAsserts(insets);
    }

    @Test
    public void testWindowInsets_root() {
        final TestActivity activity = launchAndWait(mTestActivity);

        WindowInsets insets = getOnMainSync(activity::getRootInsets);
        Assert.assertThat("test setup failed, no insets at root", insets, notNullValue());

        commonAsserts(insets);
    }

    /**
     * Tests whether an activity in split screen gets the top insets force consumed if
     * {@link View#SYSTEM_UI_FLAG_FULLSCREEN} is set, and doesn't otherwise.
     */
    @Test
    public void testForcedConsumedTopInsets() throws Exception {
        assumeTrue("Skipping test: no split multi-window support",
                supportsSplitScreenMultiWindow());

        final TestActivity activity = launchAndWait(mTestActivity);
        final int rotation = activity.getDisplay().getRotation();
        final boolean isPortrait = activity.getResources().getConfiguration()
                .orientation == ORIENTATION_PORTRAIT;
        final RotationSession rotationSession = createManagedRotationSession();
        if (isPortrait) {
            // Rotate to landscape.
            rotationSession.set(rotation == ROTATION_0 || rotation == ROTATION_180
                    ? ROTATION_90 : ROTATION_0);
        } else {
            // Keep in landscape.
            rotationSession.set(rotation);
        }

        mWmState.waitForValidState(mTestActivityComponentName);
        final int taskId = mWmState.getTaskByActivity(mTestActivityComponentName).mTaskId;
        launchActivityInPrimarySplit(LAUNCHING_ACTIVITY);
        mTaskOrganizer.putTaskInSplitSecondary(taskId);
        mWmState.waitForValidState(mTestActivityComponentName);

        // Ensure that top insets are not consumed for LAYOUT_FULLSCREEN
        WindowInsets insets = getOnMainSync(activity::getDispatchedInsets);
        final WindowInsets rootInsets = getOnMainSync(activity::getRootInsets);
        assertEquals("top inset must be dispatched in split screen",
                rootInsets.getSystemWindowInsetTop(), insets.getSystemWindowInsetTop());

        // Ensure that top insets are fully consumed for FULLSCREEN
        final TestActivity fullscreenActivity = launchAndWait(mFullscreenTestActivity);
        insets = getOnMainSync(fullscreenActivity::getDispatchedInsets);
        assertEquals("top insets must be consumed if FULLSCREEN is set",
                0, insets.getSystemWindowInsetTop());

        // Ensure that top insets are fully consumed for FULLSCREEN when setting it over wm
        // layout params
        final TestActivity fullscreenWmFlagsActivity =
                launchAndWait(mFullscreenWmFlagsTestActivity);
        insets = getOnMainSync(fullscreenWmFlagsActivity::getDispatchedInsets);
        assertEquals("top insets must be consumed if FULLSCREEN is set",
                0, insets.getSystemWindowInsetTop());
    }

    @Test
    public void testNonAutomotiveFullScreenNotBlockedBySystemComponents() {
        assumeFalse("Skipping test: Automotive is allowed to partially block fullscreen "
                        + "applications with system bars.", isAutomotive());

        final TestActivity fullscreenActivity = launchAndWait(mFullscreenTestActivity);
        View decorView = fullscreenActivity.getDecorView();
        View contentView = decorView.findViewById(android.R.id.content);
        boolean hasFullWidth = decorView.getMeasuredWidth() == contentView.getMeasuredWidth();
        boolean hasFullHeight = decorView.getMeasuredHeight() == contentView.getMeasuredHeight();

        assertTrue(hasFullWidth && hasFullHeight);
    }

    @Test
    public void testImmersiveFullscreenHidesSystemBars() throws Throwable {
        // Run the test twice, because the issue that shows system bars even in the immersive mode,
        // happens at the 2nd try.
        for (int i = 1; i <= 2; ++i) {
            Log.d(TAG, "testImmersiveFullscreenHidesSystemBars: try" + i);

            TestActivity immersiveActivity = launchAndWait(mImmersiveTestActivity);
            WindowInsets insets = getOnMainSync(immersiveActivity::getDispatchedInsets);

            assertFalse(insets.isVisible(WindowInsets.Type.statusBars()));
            assertFalse(insets.isVisible(WindowInsets.Type.navigationBars()));

            WindowInsets rootInsets = getOnMainSync(immersiveActivity::getRootInsets);
            assertFalse(rootInsets.isVisible(WindowInsets.Type.statusBars()));
            assertFalse(rootInsets.isVisible(WindowInsets.Type.navigationBars()));

            View statusBarBgView = getOnMainSync(immersiveActivity::getStatusBarBackgroundView);
            // The status bar background view can be non-existent or invisible.
            assertTrue(statusBarBgView == null
                    || statusBarBgView.getVisibility() == android.view.View.INVISIBLE);

            View navigationBarBgView = getOnMainSync(
                    immersiveActivity::getNavigationBarBackgroundView);
            // The navigation bar background view can be non-existent or invisible.
            assertTrue(navigationBarBgView == null
                    || navigationBarBgView.getVisibility() == android.view.View.INVISIBLE);
        }
    }

    private void commonAsserts(WindowInsets insets) {
        assertForAllInsets("must be non-negative", insets, insetsGreaterThanOrEqualTo(Insets.NONE));

        assertThat("system gesture insets must include mandatory system gesture insets",
                insets.getMandatorySystemGestureInsets(),
                insetsLessThanOrEqualTo(insets.getSystemGestureInsets()));

        Insets stableAndSystem = Insets.min(insets.getSystemWindowInsets(),
                insets.getStableInsets());
        assertThat("mandatory system gesture insets must include intersection between "
                        + "stable and system window insets",
                stableAndSystem,
                insetsLessThanOrEqualTo(insets.getMandatorySystemGestureInsets()));

        assertThat("tappable insets must be at most system window insets",
                insets.getTappableElementInsets(),
                insetsLessThanOrEqualTo(insets.getSystemWindowInsets()));
    }

    private void assertForAllInsets(String reason, WindowInsets actual,
            Matcher<? super Insets> matcher) {
        assertThat("getSystemWindowInsets" + ": " + reason,
                actual.getSystemWindowInsets(), matcher);
        assertThat("getStableInsets" + ": " + reason,
                actual.getStableInsets(), matcher);
        assertThat("getSystemGestureInsets" + ": " + reason,
                actual.getSystemGestureInsets(), matcher);
        assertThat("getMandatorySystemGestureInsets" + ": " + reason,
                actual.getMandatorySystemGestureInsets(), matcher);
        assertThat("getTappableElementInsets" + ": " + reason,
                actual.getTappableElementInsets(), matcher);
    }

    private <T> void assertThat(String reason, T actual, Matcher<? super T> matcher) {
        mErrorCollector.checkThat(reason, actual, matcher);
    }

    private <R> R getOnMainSync(Supplier<R> f) {
        final Object[] result = new Object[1];
        runOnMainSync(() -> result[0] = f.get());
        //noinspection unchecked
        return (R) result[0];
    }

    private void runOnMainSync(Runnable runnable) {
        getInstrumentation().runOnMainSync(runnable);
    }

    private <T extends Activity> T launchAndWait(ActivityTestRule<T> rule) {
        final T activity = rule.launchActivity(null);
        WindowUtil.waitForFocus(activity);
        return activity;
    }

    private boolean isAutomotive() {
        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
    }

    private static Matcher<Insets> insetsLessThanOrEqualTo(Insets max) {
        return new CustomTypeSafeMatcher<Insets>("must be smaller on each side than " + max) {
            @Override
            protected boolean matchesSafely(Insets actual) {
                return actual.left <= max.left && actual.top <= max.top
                        && actual.right <= max.right && actual.bottom <= max.bottom;
            }
        };
    }

    private static Matcher<Insets> insetsGreaterThanOrEqualTo(Insets min) {
        return new CustomTypeSafeMatcher<Insets>("must be greater on each side than " + min) {
            @Override
            protected boolean matchesSafely(Insets actual) {
                return actual.left >= min.left && actual.top >= min.top
                        && actual.right >= min.right && actual.bottom >= min.bottom;
            }
        };
    }

    public static class TestActivity extends Activity {

        private WindowInsets mDispatchedInsets;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getWindow().requestFeature(Window.FEATURE_NO_TITLE);
            View view = new View(this);
            view.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
            getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
            view.setOnApplyWindowInsetsListener((v, insets) -> mDispatchedInsets = insets);
            setContentView(view);
        }

        View getDecorView() {
            return getWindow().getDecorView();
        }

        View getStatusBarBackgroundView() {
            return getWindow().getStatusBarBackgroundView();
        }

        View getNavigationBarBackgroundView() {
            return getWindow().getNavigationBarBackgroundView();
        }

        WindowInsets getRootInsets() {
            return getWindow().getDecorView().getRootWindowInsets();
        }

        WindowInsets getDispatchedInsets() {
            return mDispatchedInsets;
        }
    }

    public static class FullscreenTestActivity extends TestActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getDecorView().setSystemUiVisibility(
                    getDecorView().getSystemUiVisibility() | View.SYSTEM_UI_FLAG_FULLSCREEN);
        }
    }

    public static class FullscreenWmFlagsTestActivity extends TestActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getWindow().addFlags(LayoutParams.FLAG_FULLSCREEN);
        }
    }

    public static class ImmersiveFullscreenTestActivity extends TestActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // See https://developer.android.com/training/system-ui/immersive#EnableFullscreen
            getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    // Set the content to appear under the system bars so that the
                    // content doesn't resize when the system bars hide and show.
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    // Hide the nav bar and status bar
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN);
        }
    }

    public static class NaturalOrientationTestActivity extends TestActivity {
    }
}
