/*
 * 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.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.provider.Settings.Global.ANIMATOR_DURATION_SCALE;
import static android.server.wm.CliIntentExtra.extraInt;
import static android.server.wm.ComponentNameUtils.getWindowName;
import static android.server.wm.app.Components.BACKGROUND_IMAGE_ACTIVITY;
import static android.server.wm.app.Components.BAD_BLUR_ACTIVITY;
import static android.server.wm.app.Components.BLUR_ACTIVITY;
import static android.server.wm.app.Components.BLUR_ATTRIBUTES_ACTIVITY;
import static android.server.wm.app.Components.BlurActivity.EXTRA_BACKGROUND_BLUR_RADIUS_PX;
import static android.server.wm.app.Components.BlurActivity.EXTRA_BLUR_BEHIND_RADIUS_PX;
import static android.server.wm.app.Components.BlurActivity.EXTRA_NO_BLUR_BACKGROUND_COLOR;
import static android.view.Display.DEFAULT_DISPLAY;

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

import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.spy;

import android.content.ComponentName;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;

import androidx.test.filters.FlakyTest;

import com.android.compatibility.common.util.ColorUtils;
import com.android.compatibility.common.util.SystemUtil;

import java.util.function.Consumer;

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

@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
public class BlurTests extends WindowManagerTestBase {
    private static final int BACKGROUND_BLUR_PX = 80;
    private static final int BLUR_BEHIND_PX = 40;
    private static final int NO_BLUR_BACKGROUND_COLOR = Color.BLACK;
    private static final int BLUR_BEHIND_DYNAMIC_UPDATE_WAIT_TIME = 300;
    private static final int BACKGROUND_BLUR_DYNAMIC_UPDATE_WAIT_TIME = 100;
    private static final int DISABLE_BLUR_BROADCAST_WAIT_TIME = 100;
    private float mSavedAnimatorDurationScale;
    private boolean mSavedWindowBlurDisabledSetting;

    @Before
    public void setUp() {
        assumeTrue(supportsBlur());

        mSavedWindowBlurDisabledSetting = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.DISABLE_WINDOW_BLURS, 0) == 1;
        setForceBlurDisabled(false);
        SystemUtil.runWithShellPermissionIdentity(() -> {
            final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
            mSavedAnimatorDurationScale =
                    Settings.Global.getFloat(resolver, ANIMATOR_DURATION_SCALE, 1f);
            Settings.Global.putFloat(resolver, ANIMATOR_DURATION_SCALE, 0);
        });
        startTestActivity(BACKGROUND_IMAGE_ACTIVITY);
        verifyOnlyBackgroundImageVisible();
        assertTrue(mContext.getSystemService(WindowManager.class).isCrossWindowBlurEnabled());
    }

    @After
    public void tearDown() {
        if (!supportsBlur()) return;

        SystemUtil.runWithShellPermissionIdentity(() -> {
            Settings.Global.putFloat(getInstrumentation().getContext().getContentResolver(),
                    ANIMATOR_DURATION_SCALE, mSavedAnimatorDurationScale);
        });
        setForceBlurDisabled(mSavedWindowBlurDisabledSetting);
    }

    @Test
    public void testBackgroundBlurSimple() {
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BACKGROUND_BLUR_RADIUS_PX, BACKGROUND_BLUR_PX));

        final Rect windowFrame = getWindowFrame(BLUR_ACTIVITY);
        assertBackgroundBlur(takeScreenshot(), windowFrame);
    }

    @Test
    public void testBlurBehindSimple() {
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BLUR_BEHIND_RADIUS_PX, BLUR_BEHIND_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, NO_BLUR_BACKGROUND_COLOR));

        final Bitmap screenshot = takeScreenshot();
        final Rect windowFrame = getWindowFrame(BLUR_ACTIVITY);
        assertBlurBehind(screenshot, windowFrame);
        assertNoBackgroundBlur(screenshot, windowFrame);
    }

    @Test
    public void testNoBackgroundBlurWhenBlurDisabled() {
        setForceBlurDisabled(true);
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BACKGROUND_BLUR_RADIUS_PX, BACKGROUND_BLUR_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, Color.TRANSPARENT));
        verifyOnlyBackgroundImageVisible();
    }

    @Test
    public void testNoBackgroundBlurForNonTranslucentWindow() {
        startTestActivity(BAD_BLUR_ACTIVITY,
                          extraInt(EXTRA_BACKGROUND_BLUR_RADIUS_PX, BACKGROUND_BLUR_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, Color.TRANSPARENT));
        verifyOnlyBackgroundImageVisible();
    }

    @Test
    public void testNoBlurBehindWhenBlurDisabled() {
        setForceBlurDisabled(true);
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BLUR_BEHIND_RADIUS_PX, BLUR_BEHIND_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, Color.TRANSPARENT));
        verifyOnlyBackgroundImageVisible();
    }

    @Test
    public void testNoBlurBehindWhenFlagNotSet() {
        startTestActivity(BAD_BLUR_ACTIVITY,
                          extraInt(EXTRA_BLUR_BEHIND_RADIUS_PX, BLUR_BEHIND_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, Color.TRANSPARENT));
        verifyOnlyBackgroundImageVisible();
    }

    @Test
    public void testBackgroundBlurActivatesFallbackDynamically() throws Exception {
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BACKGROUND_BLUR_RADIUS_PX, BACKGROUND_BLUR_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, NO_BLUR_BACKGROUND_COLOR));
        final Rect windowFrame = getWindowFrame(BLUR_ACTIVITY);

        Bitmap screenshot = takeScreenshot();
        assertBackgroundBlur(takeScreenshot(), windowFrame);
        assertNoBlurBehind(screenshot, windowFrame);

        setForceBlurDisabled(true);
        Thread.sleep(BACKGROUND_BLUR_DYNAMIC_UPDATE_WAIT_TIME);

        screenshot = takeScreenshot();
        assertNoBackgroundBlur(screenshot, windowFrame);
        assertNoBlurBehind(screenshot, windowFrame);

        setForceBlurDisabled(false);
        Thread.sleep(BACKGROUND_BLUR_DYNAMIC_UPDATE_WAIT_TIME);

        screenshot = takeScreenshot();
        assertBackgroundBlur(takeScreenshot(), windowFrame);
        assertNoBlurBehind(screenshot, windowFrame);
    }

    @Test
    public void testBlurBehindDisabledDynamically() throws Exception {
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BLUR_BEHIND_RADIUS_PX, BLUR_BEHIND_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, NO_BLUR_BACKGROUND_COLOR));
        final Rect windowFrame = getWindowFrame(BLUR_ACTIVITY);

        Bitmap screenshot = takeScreenshot();
        assertBlurBehind(screenshot, windowFrame);
        assertNoBackgroundBlur(screenshot, windowFrame);

        setForceBlurDisabled(true);
        Thread.sleep(BLUR_BEHIND_DYNAMIC_UPDATE_WAIT_TIME);

        screenshot = takeScreenshot();
        assertNoBackgroundBlur(screenshot, windowFrame);
        assertNoBlurBehind(screenshot, windowFrame);

        setForceBlurDisabled(false);
        Thread.sleep(BLUR_BEHIND_DYNAMIC_UPDATE_WAIT_TIME);

        screenshot = takeScreenshot();
        assertBlurBehind(screenshot,  windowFrame);
        assertNoBackgroundBlur(screenshot, windowFrame);
    }

    @Test
    public void testBlurBehindAndBackgroundBlur() throws Exception {
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BLUR_BEHIND_RADIUS_PX, BLUR_BEHIND_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, NO_BLUR_BACKGROUND_COLOR),
                          extraInt(EXTRA_BACKGROUND_BLUR_RADIUS_PX, BACKGROUND_BLUR_PX));
        final Rect windowFrame = getWindowFrame(BLUR_ACTIVITY);

        Bitmap screenshot = takeScreenshot();
        assertBlurBehind(screenshot, windowFrame);
        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);

        setForceBlurDisabled(true);
        Thread.sleep(BLUR_BEHIND_DYNAMIC_UPDATE_WAIT_TIME);

        screenshot = takeScreenshot();
        assertNoBackgroundBlur(screenshot, windowFrame);
        assertNoBlurBehind(screenshot, windowFrame);

        setForceBlurDisabled(false);
        Thread.sleep(BLUR_BEHIND_DYNAMIC_UPDATE_WAIT_TIME);

        screenshot = takeScreenshot();
        assertBlurBehind(screenshot, windowFrame);
        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);
    }

    @Test
    public void testBlurBehindAndBackgroundBlurSetWithAttributes() {
        startTestActivity(BLUR_ATTRIBUTES_ACTIVITY);
        final Rect windowFrame = getWindowFrame(BLUR_ATTRIBUTES_ACTIVITY);
        final Bitmap screenshot = takeScreenshot();

        assertBlurBehind(screenshot, windowFrame);
        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);
    }

    @Test
    public void testBlurDestroyedAfterActivityFinished() {
        startTestActivity(BLUR_ACTIVITY,
                          extraInt(EXTRA_BLUR_BEHIND_RADIUS_PX, BLUR_BEHIND_PX),
                          extraInt(EXTRA_NO_BLUR_BACKGROUND_COLOR, NO_BLUR_BACKGROUND_COLOR),
                          extraInt(EXTRA_BACKGROUND_BLUR_RADIUS_PX, BACKGROUND_BLUR_PX));
        final Rect windowFrame = getWindowFrame(BLUR_ACTIVITY);
        Bitmap screenshot = takeScreenshot();

        assertBlurBehind(screenshot, windowFrame);
        assertBackgroundBlurOverBlurBehind(screenshot, windowFrame);

        mBroadcastActionTrigger.finishBroadcastReceiverActivity();
        mWmState.waitAndAssertActivityRemoved(BLUR_ACTIVITY);

        verifyOnlyBackgroundImageVisible();
    }

    @Test
    public void testIsCrossWindowBlurEnabledUpdatedCorrectly() throws Exception {
        setForceBlurDisabled(true);
        Thread.sleep(DISABLE_BLUR_BROADCAST_WAIT_TIME);
        assertFalse(mContext.getSystemService(WindowManager.class).isCrossWindowBlurEnabled());

        setForceBlurDisabled(false);
        Thread.sleep(DISABLE_BLUR_BROADCAST_WAIT_TIME);
        assertTrue(mContext.getSystemService(WindowManager.class).isCrossWindowBlurEnabled());
    }

    @Test
    public void testBlurListener() throws Exception {
        ListenerTestActivity activity = startActivity(ListenerTestActivity.class);
        Mockito.verify(activity.mBlurEnabledListener).accept(true);

        setForceBlurDisabled(true);
        Thread.sleep(DISABLE_BLUR_BROADCAST_WAIT_TIME);
        assertFalse(mContext.getSystemService(WindowManager.class).isCrossWindowBlurEnabled());
        Mockito.verify(activity.mBlurEnabledListener).accept(false);

        setForceBlurDisabled(false);
        Thread.sleep(DISABLE_BLUR_BROADCAST_WAIT_TIME);
        assertTrue(mContext.getSystemService(WindowManager.class).isCrossWindowBlurEnabled());
        Mockito.verify(activity.mBlurEnabledListener, times(2)).accept(true);
    }

    public static class BlurListener implements Consumer<Boolean> {
        @Override
        public void accept(Boolean enabled) {}
    }

    public static class ListenerTestActivity extends FocusableActivity {
        Consumer<Boolean> mBlurEnabledListener = spy(new BlurListener());

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            View v = new LinearLayout(this);
            v.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
                @Override
                public void onViewAttachedToWindow(View view) {
                    getWindowManager().addCrossWindowBlurEnabledListener(mBlurEnabledListener);
                }

                @Override
                public void onViewDetachedFromWindow(View view) {
                    getWindowManager().removeCrossWindowBlurEnabledListener(mBlurEnabledListener);
                }
            });
            setContentView(v);
        }
    }

    private void startTestActivity(ComponentName activityName, final CliIntentExtra... extras) {
        launchActivity(activityName, extras);
        assertNotEquals(mWmState.getRootTaskIdByActivity(activityName), INVALID_STACK_ID);
        waitAndAssertResumedActivity(activityName, activityName + " must be resumed");
        mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
    }


    private Rect getWindowFrame(ComponentName activityName) {
        String windowName = getWindowName(activityName);
        mWmState.computeState(activityName);
        return mWmState.getMatchingVisibleWindowState(windowName).get(0).getFrame();
    }

    private void verifyOnlyBackgroundImageVisible() {
        final Bitmap screenshot = takeScreenshot();
        final int height = screenshot.getHeight();
        final int width = screenshot.getWidth();

        final int blueWidth = width / 2;

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                if (x < blueWidth) {
                    ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
                            Color.BLUE, screenshot.getPixel(x, y), 0);
                } else {
                    ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
                            Color.RED, screenshot.getPixel(x, y), 0);
                }
            }
        }
    }

    private static void assertBlurBehind(Bitmap screenshot, Rect windowFrame) {
        assertBlur(screenshot, BLUR_BEHIND_PX, 0, windowFrame.top);
        assertBlur(screenshot, BLUR_BEHIND_PX, windowFrame.bottom, screenshot.getHeight());
    }

    private static void assertBackgroundBlur(Bitmap screenshot, Rect windowFrame) {
        assertBlur(screenshot, BACKGROUND_BLUR_PX, windowFrame.top, windowFrame.bottom);
    }

    private static void assertBackgroundBlurOverBlurBehind(Bitmap screenshot, Rect windowFrame) {
        // We are assuming that the background blur will become bigger by roughly half of the blur
        // behind radius
        assertBlur(screenshot, BACKGROUND_BLUR_PX + ((int) (BLUR_BEHIND_PX*0.5f)),
                windowFrame.top, windowFrame.bottom);
    }

    private static void assertNoBlurBehind(Bitmap screenshot, Rect windowFrame) {
        for (int x = 0; x < screenshot.getWidth(); x++) {
            for (int y = 0; y < screenshot.getHeight(); y++) {
                if (x < windowFrame.left) {
                    ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
                            Color.BLUE, screenshot.getPixel(x, y), 0);
                } else if (x < screenshot.getWidth() / 2) {
                    if (y < windowFrame.top || y > windowFrame.bottom) {
                        ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
                                Color.BLUE, screenshot.getPixel(x, y), 0);
                    }
                } else if (x <= windowFrame.right) {
                    if (y < windowFrame.top || y > windowFrame.bottom) {
                        ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
                                Color.RED, screenshot.getPixel(x, y), 0);
                    }
                } else if (x > windowFrame.right) {
                    ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
                            Color.RED, screenshot.getPixel(x, y), 0);
                }

            }
        }
    }

    private static void assertNoBackgroundBlur(Bitmap screenshot, Rect windowFrame) {
        for (int y = windowFrame.top; y < windowFrame.bottom; y++) {
            for (int x = windowFrame.left; x < windowFrame.right; x++) {
                ColorUtils.verifyColor("failed for pixel (x, y) = (" + x + ", " + y + ")",
                        NO_BLUR_BACKGROUND_COLOR, screenshot.getPixel(x, y), 0);
            }
        }
    }

    private static void assertBlur(Bitmap screenshot, int blurRadius, int startHeight,
                                   int endHeight) {
        final int width = screenshot.getWidth();

        // Adjust the test to check a smaller part of the blurred area in order to accept various
        // blur algorithm approximations used in RenderEngine
        final int stepSize = blurRadius / 4;
        final int blurAreaStartX = width / 2 - blurRadius + stepSize;
        final int blurAreaEndX = width / 2 + blurRadius;

        Color previousColor;
        Color currentColor;
        final int unaffectedBluePixelX = width / 2 - blurRadius * 2 - 1;
        final int unaffectedRedPixelX = width / 2 + blurRadius * 2 + 1;
        for (int y = startHeight; y < endHeight; y++) {
            ColorUtils.verifyColor(
                    "failed for pixel (x, y) = (" + unaffectedBluePixelX + ", " + y + ")",
                    Color.BLUE, screenshot.getPixel(unaffectedBluePixelX, y), 0);
            previousColor = Color.valueOf(Color.BLUE);
            for (int x = blurAreaStartX; x < blurAreaEndX; x += stepSize) {
                currentColor = screenshot.getColor(x, y);
                assertTrue("assertBlur failed for blue for pixel (x, y) = (" + x + ", " + y + ");"
                        + " previousColor blue: " + previousColor.blue()
                        + ", currentColor blue: " + currentColor.blue()
                        , previousColor.blue() > currentColor.blue());
                assertTrue("assertBlur failed for red for pixel (x, y) = (" + x + ", " + y + ");"
                       + " previousColor red: " + previousColor.red()
                       + ", currentColor red: " + currentColor.red(),
                       previousColor.red() < currentColor.red());

                previousColor = currentColor;
            }
            ColorUtils.verifyColor(
                    "failed for pixel (x, y) = (" + unaffectedRedPixelX + ", " + y + ")",
                    Color.RED, screenshot.getPixel(unaffectedRedPixelX, y), 0);
        }
    }

    private void setForceBlurDisabled(boolean disable) {
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.DISABLE_WINDOW_BLURS, disable ? 1 : 0);
    }
}
