/*
 * 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 com.android.systemui.bubbles.animation;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.Mockito.verify;

import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.testing.AndroidTestingRunner;
import android.view.View;
import android.widget.FrameLayout;

import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.test.filters.SmallTest;

import com.android.systemui.R;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Spy;

@SmallTest
@RunWith(AndroidTestingRunner.class)
public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestCase {

    private int mDisplayWidth = 500;
    private int mDisplayHeight = 1000;
    private int mExpandedViewPadding = 10;

    @Spy
    private ExpandedAnimationController mExpandedController =
            new ExpandedAnimationController(
                    new Point(mDisplayWidth, mDisplayHeight) /* displaySize */,
                    mExpandedViewPadding);

    private int mStackOffset;
    private float mBubblePaddingTop;
    private float mBubbleSize;

    private PointF mExpansionPoint;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        addOneMoreThanRenderLimitBubbles();
        mLayout.setController(mExpandedController);

        Resources res = mLayout.getResources();
        mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
        mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
        mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
        mExpansionPoint = new PointF(100, 100);
    }

    @Test
    public void testExpansionAndCollapse() throws InterruptedException {
        Runnable afterExpand = Mockito.mock(Runnable.class);
        mExpandedController.expandFromStack(mExpansionPoint, afterExpand);
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);

        testBubblesInCorrectExpandedPositions();
        verify(afterExpand).run();

        Runnable afterCollapse = Mockito.mock(Runnable.class);
        mExpandedController.collapseBackToStack(afterCollapse);
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);

        testStackedAtPosition(mExpansionPoint.x, mExpansionPoint.y, -1);
        verify(afterExpand).run();
    }

    @Test
    public void testOnChildAdded() throws InterruptedException {
        expand();

        // Add another new view and wait for its animation.
        final View newView = new FrameLayout(getContext());
        mLayout.addView(newView, 0);
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);

        testBubblesInCorrectExpandedPositions();
    }

    @Test
    public void testOnChildRemoved() throws InterruptedException {
        expand();

        // Remove some views and see if the remaining child views still pass the expansion test.
        mLayout.removeView(mViews.get(0));
        mLayout.removeView(mViews.get(3));
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
        testBubblesInCorrectExpandedPositions();
    }

    @Test
    public void testBubbleDraggedNotDismissedSnapsBack() throws InterruptedException {
        expand();

        final View draggedBubble = mViews.get(0);
        mExpandedController.prepareForBubbleDrag(draggedBubble);
        mExpandedController.dragBubbleOut(draggedBubble, 500f, 500f);

        assertEquals(500f, draggedBubble.getTranslationX(), 1f);
        assertEquals(500f, draggedBubble.getTranslationY(), 1f);

        // Snap it back and make sure it made it back correctly.
        mExpandedController.snapBubbleBack(draggedBubble, 0f, 0f);
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
        testBubblesInCorrectExpandedPositions();
    }

    @Test
    public void testBubbleDismissed() throws InterruptedException {
        expand();

        final View draggedBubble = mViews.get(0);
        mExpandedController.prepareForBubbleDrag(draggedBubble);
        mExpandedController.dragBubbleOut(draggedBubble, 500f, 500f);

        assertEquals(500f, draggedBubble.getTranslationX(), 1f);
        assertEquals(500f, draggedBubble.getTranslationY(), 1f);

        // Snap bubble back and make sure it returned correctly.
        mExpandedController.prepareForDismissalWithVelocity(draggedBubble);
        mLayout.removeView(draggedBubble);
        waitForLayoutMessageQueue();
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);

        assertEquals(-1, mLayout.indexOfChild(draggedBubble));
        testBubblesInCorrectExpandedPositions();
    }

    @Test
    @Ignore("Flaky")
    public void testMagnetToDismiss_dismiss() throws InterruptedException {
        expand();

        final View draggedOutView = mViews.get(0);
        final Runnable after = Mockito.mock(Runnable.class);

        mExpandedController.prepareForBubbleDrag(draggedOutView);
        mExpandedController.dragBubbleOut(draggedOutView, 25, 25);

        // Magnet to dismiss, verify the bubble is at the dismiss target and the callback was
        // called.
        mExpandedController.magnetBubbleToDismiss(
                mViews.get(0), 100 /* velX */, 100 /* velY */, 1000 /* destY */, after);
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
        verify(after).run();
        assertEquals(1000, mViews.get(0).getTranslationY(), .1f);

        // Dismiss the now-magneted bubble, verify that the callback was called.
        final Runnable afterDismiss = Mockito.mock(Runnable.class);
        mExpandedController.dismissDraggedOutBubble(afterDismiss);
        waitForPropertyAnimations(DynamicAnimation.ALPHA);
        verify(after).run();

        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);

        assertEquals(mBubblePaddingTop, mViews.get(1).getTranslationX(), 1f);
    }

    @Test
    @Ignore("Flaky")
    public void testMagnetToDismiss_demagnetizeThenDrag() throws InterruptedException {
        expand();

        final View draggedOutView = mViews.get(0);
        final Runnable after = Mockito.mock(Runnable.class);

        mExpandedController.prepareForBubbleDrag(draggedOutView);
        mExpandedController.dragBubbleOut(draggedOutView, 25, 25);

        // Magnet to dismiss, verify the bubble is at the dismiss target and the callback was
        // called.
        mExpandedController.magnetBubbleToDismiss(
                draggedOutView, 100 /* velX */, 100 /* velY */, 1000 /* destY */, after);
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
        verify(after).run();
        assertEquals(1000, mViews.get(0).getTranslationY(), .1f);

        // Demagnetize the bubble towards (25, 25).
        mExpandedController.demagnetizeBubbleTo(25 /* x */, 25 /* y */, 100, 100);

        // Start dragging towards (20, 20).
        mExpandedController.dragBubbleOut(draggedOutView, 20, 20);

        // Since we just demagnetized, the bubble shouldn't be at (20, 20), it should be animating
        // towards it.
        assertNotEquals(20, draggedOutView.getTranslationX());
        assertNotEquals(20, draggedOutView.getTranslationY());
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);

        // Waiting for the animations should result in the bubble ending at (20, 20) since the
        // animation end value was updated.
        assertEquals(20, draggedOutView.getTranslationX(), 1f);
        assertEquals(20, draggedOutView.getTranslationY(), 1f);

        // Drag to (30, 30).
        mExpandedController.dragBubbleOut(draggedOutView, 30, 30);

        // It should go there instantly since the animations finished.
        assertEquals(30, draggedOutView.getTranslationX(), 1f);
        assertEquals(30, draggedOutView.getTranslationY(), 1f);
    }

    /** Expand the stack and wait for animations to finish. */
    private void expand() throws InterruptedException {
        mExpandedController.expandFromStack(mExpansionPoint, Mockito.mock(Runnable.class));
        waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
    }

    /** Check that children are in the correct positions for being stacked. */
    private void testStackedAtPosition(float x, float y, int offsetMultiplier) {
        // Make sure the rest of the stack moved again, including the first bubble not moving, and
        // is stacked to the right now that we're on the right side of the screen.
        for (int i = 0; i < mLayout.getChildCount(); i++) {
            assertEquals(x + i * offsetMultiplier * mStackOffset,
                    mLayout.getChildAt(i).getTranslationX(), 2f);
            assertEquals(y, mLayout.getChildAt(i).getTranslationY(), 2f);

            if (i < mMaxRenderedBubbles) {
                assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
            }
        }
    }

    /** Check that children are in the correct positions for being expanded. */
    private void testBubblesInCorrectExpandedPositions() {
        // Check all the visible bubbles to see if they're in the right place.
        for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) {
            assertEquals(getBubbleLeft(i),
                    mLayout.getChildAt(i).getTranslationX(),
                    2f);
            assertEquals(mExpandedController.getExpandedY(),
                    mLayout.getChildAt(i).getTranslationY(), 2f);

            if (i < mMaxRenderedBubbles) {
                assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
            }
        }
    }

    /**
     * @param index Bubble index in row.
     * @return Bubble left x from left edge of screen.
     */
    public float getBubbleLeft(int index) {
        final float bubbleLeft = index * (mBubbleSize + getSpaceBetweenBubbles());
        return getRowLeft() + bubbleLeft;
    }

    private float getRowLeft() {
        if (mLayout == null) {
            return 0;
        }
        int bubbleCount = mLayout.getChildCount();
        if (bubbleCount > mMaxRenderedBubbles) {
            bubbleCount = mMaxRenderedBubbles;
        }
        final float totalBubbleWidth = bubbleCount * mBubbleSize;
        final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
        final float rowWidth = totalGapWidth + totalBubbleWidth;

        final float centerScreen = mDisplayWidth / 2f;
        final float halfRow = rowWidth / 2f;
        final float rowLeft = centerScreen - halfRow;

        return rowLeft;
    }

    /**
     * @return Space between bubbles in row above expanded view.
     */
    private float getSpaceBetweenBubbles() {
        final float launcherGridDiff = mBubbleSize / 2f;
        final float rowMargins = (mExpandedViewPadding + launcherGridDiff) * 2;
        final float maxRowWidth = mDisplayWidth - rowMargins;

        final float totalBubbleWidth = mMaxRenderedBubbles * mBubbleSize;
        final float totalGapWidth = maxRowWidth - totalBubbleWidth;

        final int gapCount = mMaxRenderedBubbles - 1;
        final float gapWidth = totalGapWidth / gapCount;
        return gapWidth;
    }
}
