/*
 * 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;

import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.server.wm.RoundedCornerTests.TestActivity.EXTRA_ORIENTATION;
import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT;
import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT;
import static android.view.RoundedCorner.POSITION_TOP_LEFT;
import static android.view.RoundedCorner.POSITION_TOP_RIGHT;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;

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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.RoundedCorner;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;

import androidx.test.rule.ActivityTestRule;

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

import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@Presubmit
@RunWith(Parameterized.class)
public class RoundedCornerTests {
    private static final String TAG = "RoundedCornerTests";
    private final static int POSITION_LENGTH = 4;
    private final static long TIMEOUT = 1000; // milliseconds

    @Parameterized.Parameters(name= "{1}({0})")
    public static Object[][] data() {
        return new Object[][]{
                {SCREEN_ORIENTATION_PORTRAIT, "SCREEN_ORIENTATION_PORTRAIT"},
                {SCREEN_ORIENTATION_LANDSCAPE, "SCREEN_ORIENTATION_LANDSCAPE"},
                {SCREEN_ORIENTATION_REVERSE_LANDSCAPE, "SCREEN_ORIENTATION_REVERSE_LANDSCAPE"},
                {SCREEN_ORIENTATION_REVERSE_PORTRAIT, "SCREEN_ORIENTATION_REVERSE_PORTRAIT"},
        };
    }

    @Parameterized.Parameter(0)
    public int orientation;

    @Parameterized.Parameter(1)
    public String orientationName;

    @After
    public void tearDown() {
        mTestActivity.finishActivity();
        new WindowManagerStateHelper().waitForDisplayUnfrozen();
    }

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

    @Test
    public void testRoundedCorner_fullscreen() {
        final TestActivity activity = mTestActivity.launchActivity(
                new Intent().putExtra(EXTRA_ORIENTATION, orientation));
        runOnMainSync(() -> {
            activity.addChildWindow(
                    activity.calculateWindowBounds(false /* excludeRoundedCorners */));
        });
        // Make sure the child window has been laid out.
        final View childWindowRoot = activity.getChildWindowRoot();
        PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot.getWidth() > 0);
        PollingCheck.waitFor(TIMEOUT, () -> activity.getDispatchedInsets() != null);
        final WindowInsets insets = activity.getDispatchedInsets();

        final Display display = activity.getDisplay();
        for (int i = 0; i < POSITION_LENGTH; i++) {
            assertEquals(insets.getRoundedCorner(i), display.getRoundedCorner(i));
        }
    }

    @Test
    public void testRoundedCorner_excludeRoundedCorners() {
        final TestActivity activity = mTestActivity.launchActivity(
                new Intent().putExtra(EXTRA_ORIENTATION, orientation));
        if (!activity.hasRoundedCorners()) {
            Log.d(TAG, "There is no rounded corner on the display. Skipped!!");
            return;
        }
        runOnMainSync(() -> {
            activity.addChildWindow(
                    activity.calculateWindowBounds(true /* excludeRoundedCorners */));
        });

        // Make sure the child window has been laid out.
        final View childWindowRoot = activity.getChildWindowRoot();
        PollingCheck.waitFor(TIMEOUT, () -> childWindowRoot.getWidth() > 0);
        PollingCheck.waitFor(TIMEOUT, () -> activity.getDispatchedInsets() != null);
        final WindowInsets insets = activity.getDispatchedInsets();

        for (int i = 0; i < POSITION_LENGTH; i++) {
            assertNull("The rounded corners should be null.", insets.getRoundedCorner(i));
        }
    }

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

    public static class TestActivity extends Activity {
        static final String EXTRA_ORIENTATION = "extra.orientation";

        private View mChildWindowRoot;
        private WindowInsets mDispatchedInsets;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getWindow().requestFeature(Window.FEATURE_NO_TITLE);
            getWindow().getAttributes().layoutInDisplayCutoutMode =
                    LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
            if (getIntent() != null) {
                setRequestedOrientation(getIntent().getIntExtra(
                        EXTRA_ORIENTATION, SCREEN_ORIENTATION_UNSPECIFIED));
            }
        }

        void addChildWindow(Rect bounds) {
            final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
            attrs.x = bounds.left;
            attrs.y = bounds.top;
            attrs.width = bounds.width();
            attrs.height = bounds.height();
            attrs.gravity = Gravity.LEFT | Gravity.TOP;
            attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
            attrs.flags = FLAG_NOT_FOCUSABLE;
            attrs.setFitInsetsTypes(0);
            mChildWindowRoot = new View(this);
            mChildWindowRoot.setOnApplyWindowInsetsListener(
                    (v, insets) -> mDispatchedInsets = insets);
            getWindowManager().addView(mChildWindowRoot, attrs);
        }

        View getChildWindowRoot() {
            return mChildWindowRoot;
        }

        WindowInsets getDispatchedInsets() {
            return mDispatchedInsets;
        }

        boolean hasRoundedCorners() {
            final Display display = getDisplay();
            return display.getRoundedCorner(POSITION_TOP_LEFT) != null
                    || display.getRoundedCorner(POSITION_TOP_RIGHT) != null
                    || display.getRoundedCorner(POSITION_BOTTOM_RIGHT) != null
                    || display.getRoundedCorner(POSITION_BOTTOM_LEFT) != null;
        }

        Rect calculateWindowBounds(boolean excludeRoundedCorners) {
            final Display display = getDisplay();
            final WindowMetrics windowMetrics = getWindowManager().getMaximumWindowMetrics();
            if (!excludeRoundedCorners) {
                return windowMetrics.getBounds();
            }
            final Rect bounds = new Rect();
            final int width = windowMetrics.getBounds().width();
            final int height = windowMetrics.getBounds().height();
            final RoundedCorner topLeft = display.getRoundedCorner(POSITION_TOP_LEFT);
            final RoundedCorner topRight = display.getRoundedCorner(POSITION_TOP_RIGHT);
            final RoundedCorner bottomRight = display.getRoundedCorner(POSITION_BOTTOM_RIGHT);
            final RoundedCorner bottomLeft = display.getRoundedCorner(POSITION_BOTTOM_LEFT);

            bounds.left = Math.max(topLeft != null ? topLeft.getCenter().x : 0,
                    bottomLeft != null ? bottomLeft.getCenter().x : 0);
            bounds.top = Math.max(topLeft != null ? topLeft.getCenter().y : 0,
                    bottomLeft != null ? bottomLeft.getCenter().y : 0);
            bounds.right = Math.min(topRight != null ? topRight.getCenter().x : width,
                    bottomRight != null ? bottomRight.getCenter().x : width);
            bounds.bottom = Math.min(bottomRight != null ? bottomRight.getCenter().y : height,
                    bottomLeft != null ? bottomLeft.getCenter().y : height);

            Log.d(TAG, "Window bounds with rounded corners excluded = " + bounds);
            return bounds;
        }
    }
}
