/*
 * 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 android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.Log;
import android.view.View;
import android.view.WindowInsets;

import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.FlingAnimation;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;

import com.android.systemui.R;

import com.google.android.collect.Sets;

import java.util.HashMap;
import java.util.Set;

/**
 * Animation controller for bubbles when they're in their stacked state. Stacked bubbles sit atop
 * each other with a slight offset to the left or right (depending on which side of the screen they
 * are on). Bubbles 'follow' each other when dragged, and can be flung to the left or right sides of
 * the screen.
 */
public class StackAnimationController extends
        PhysicsAnimationLayout.PhysicsAnimationController {

    private static final String TAG = "Bubbs.StackCtrl";

    /** Scale factor to use initially for new bubbles being animated in. */
    private static final float ANIMATE_IN_STARTING_SCALE = 1.15f;

    /** Translation factor (multiplied by stack offset) to use for bubbles being animated in/out. */
    private static final int ANIMATE_TRANSLATION_FACTOR = 4;

    /**
     * Values to use for the default {@link SpringForce} provided to the physics animation layout.
     */
    private static final int DEFAULT_STIFFNESS = 12000;
    private static final int FLING_FOLLOW_STIFFNESS = 20000;
    private static final float DEFAULT_BOUNCINESS = 0.9f;

    /**
     * Friction applied to fling animations. Since the stack must land on one of the sides of the
     * screen, we want less friction horizontally so that the stack has a better chance of making it
     * to the side without needing a spring.
     */
    private static final float FLING_FRICTION_X = 2.2f;
    private static final float FLING_FRICTION_Y = 2.2f;

    /**
     * Values to use for the stack spring animation used to spring the stack to its final position
     * after a fling.
     */
    private static final int SPRING_AFTER_FLING_STIFFNESS = 750;
    private static final float SPRING_AFTER_FLING_DAMPING_RATIO = 0.85f;

    /**
     * Minimum fling velocity required to trigger moving the stack from one side of the screen to
     * the other.
     */
    private static final float ESCAPE_VELOCITY = 750f;

    /**
     * The canonical position of the stack. This is typically the position of the first bubble, but
     * we need to keep track of it separately from the first bubble's translation in case there are
     * no bubbles, or the first bubble was just added and being animated to its new position.
     */
    private PointF mStackPosition = new PointF(-1, -1);

    /** Whether or not the stack's start position has been set. */
    private boolean mStackMovedToStartPosition = false;

    /** The most recent position in which the stack was resting on the edge of the screen. */
    private PointF mRestingStackPosition;

    /** The height of the most recently visible IME. */
    private float mImeHeight = 0f;

    /**
     * The Y position of the stack before the IME became visible, or {@link Float#MIN_VALUE} if the
     * IME is not visible or the user moved the stack since the IME became visible.
     */
    private float mPreImeY = Float.MIN_VALUE;

    /**
     * Animations on the stack position itself, which would have been started in
     * {@link #flingThenSpringFirstBubbleWithStackFollowing}. These animations dispatch to
     * {@link #moveFirstBubbleWithStackFollowing} to move the entire stack (with 'following' effect)
     * to a legal position on the side of the screen.
     */
    private HashMap<DynamicAnimation.ViewProperty, DynamicAnimation> mStackPositionAnimations =
            new HashMap<>();

    /**
     * Whether the current motion of the stack is due to a fling animation (vs. being dragged
     * manually).
     */
    private boolean mIsMovingFromFlinging = false;

    /**
     * Whether the stack is within the dismiss target (either by being dragged, magnet'd, or flung).
     */
    private boolean mWithinDismissTarget = false;

    /**
     * Whether the first bubble is springing towards the touch point, rather than using the default
     * behavior of moving directly to the touch point with the rest of the stack following it.
     *
     * This happens when the user's finger exits the dismiss area while the stack is magnetized to
     * the center. Since the touch point differs from the stack location, we need to animate the
     * stack back to the touch point to avoid a jarring instant location change from the center of
     * the target to the touch point just outside the target bounds.
     *
     * This is reset once the spring animations end, since that means the first bubble has
     * successfully 'caught up' to the touch.
     */
    private boolean mFirstBubbleSpringingToTouch = false;

    /** Horizontal offset of bubbles in the stack. */
    private float mStackOffset;
    /** Diameter of the bubbles themselves. */
    private int mIndividualBubbleSize;
    /**
     * The amount of space to add between the bubbles and certain UI elements, such as the top of
     * the screen or the IME. This does not apply to the left/right sides of the screen since the
     * stack goes offscreen intentionally.
     */
    private int mBubblePadding;
    /** How far offscreen the stack rests. */
    private int mBubbleOffscreen;
    /** How far down the screen the stack starts, when there is no pre-existing location. */
    private int mStackStartingVerticalOffset;
    /** Height of the status bar. */
    private float mStatusBarHeight;

    /**
     * Instantly move the first bubble to the given point, and animate the rest of the stack behind
     * it with the 'following' effect.
     */
    public void moveFirstBubbleWithStackFollowing(float x, float y) {
        // If we manually move the bubbles with the IME open, clear the return point since we don't
        // want the stack to snap away from the new position.
        mPreImeY = Float.MIN_VALUE;

        moveFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_X, x);
        moveFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_Y, y);

        // This method is called when the stack is being dragged manually, so we're clearly no
        // longer flinging.
        mIsMovingFromFlinging = false;
    }

    /**
     * The position of the stack - typically the position of the first bubble; if no bubbles have
     * been added yet, it will be where the first bubble will go when added.
     */
    public PointF getStackPosition() {
        return mStackPosition;
    }

    /** Whether the stack is on the left side of the screen. */
    public boolean isStackOnLeftSide() {
        if (mLayout == null || !isStackPositionSet()) {
            return false;
        }

        float stackCenter = mStackPosition.x + mIndividualBubbleSize / 2;
        float screenCenter = mLayout.getWidth() / 2;
        return stackCenter < screenCenter;
    }

    /**
     * Fling stack to given corner, within allowable screen bounds.
     * Note that we need new SpringForce instances per animation despite identical configs because
     * SpringAnimation uses SpringForce's internal (changing) velocity while the animation runs.
     */
    public void springStack(float destinationX, float destinationY) {
        springFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_X,
                    new SpringForce()
                        .setStiffness(SPRING_AFTER_FLING_STIFFNESS)
                        .setDampingRatio(SPRING_AFTER_FLING_DAMPING_RATIO),
                    0 /* startXVelocity */,
                    destinationX);

        springFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_Y,
                    new SpringForce()
                        .setStiffness(SPRING_AFTER_FLING_STIFFNESS)
                        .setDampingRatio(SPRING_AFTER_FLING_DAMPING_RATIO),
                    0 /* startYVelocity */,
                    destinationY);
    }

    /**
     * Flings the stack starting with the given velocities, springing it to the nearest edge
     * afterward.
     *
     * @return The X value that the stack will end up at after the fling/spring.
     */
    public float flingStackThenSpringToEdge(float x, float velX, float velY) {
        final boolean stackOnLeftSide = x - mIndividualBubbleSize / 2 < mLayout.getWidth() / 2;

        final boolean stackShouldFlingLeft = stackOnLeftSide
                ? velX < ESCAPE_VELOCITY
                : velX < -ESCAPE_VELOCITY;

        final RectF stackBounds = getAllowableStackPositionRegion();

        // Target X translation (either the left or right side of the screen).
        final float destinationRelativeX = stackShouldFlingLeft
                ? stackBounds.left : stackBounds.right;

        // Minimum velocity required for the stack to make it to the targeted side of the screen,
        // taking friction into account (4.2f is the number that friction scalars are multiplied by
        // in DynamicAnimation.DragForce). This is an estimate - it could possibly be slightly off,
        // but the SpringAnimation at the end will ensure that it reaches the destination X
        // regardless.
        final float minimumVelocityToReachEdge =
                (destinationRelativeX - x) * (FLING_FRICTION_X * 4.2f);

        // Use the touch event's velocity if it's sufficient, otherwise use the minimum velocity so
        // that it'll make it all the way to the side of the screen.
        final float startXVelocity = stackShouldFlingLeft
                ? Math.min(minimumVelocityToReachEdge, velX)
                : Math.max(minimumVelocityToReachEdge, velX);

        flingThenSpringFirstBubbleWithStackFollowing(
                DynamicAnimation.TRANSLATION_X,
                startXVelocity,
                FLING_FRICTION_X,
                new SpringForce()
                        .setStiffness(SPRING_AFTER_FLING_STIFFNESS)
                        .setDampingRatio(SPRING_AFTER_FLING_DAMPING_RATIO),
                destinationRelativeX);

        flingThenSpringFirstBubbleWithStackFollowing(
                DynamicAnimation.TRANSLATION_Y,
                velY,
                FLING_FRICTION_Y,
                new SpringForce()
                        .setStiffness(SPRING_AFTER_FLING_STIFFNESS)
                        .setDampingRatio(SPRING_AFTER_FLING_DAMPING_RATIO),
                /* destination */ null);

        mLayout.setEndActionForMultipleProperties(
                () -> {
                    mRestingStackPosition = new PointF();
                    mRestingStackPosition.set(mStackPosition);
                    mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_X);
                    mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_Y);
                },
                DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);

        // If we're flinging now, there's no more touch event to catch up to.
        mFirstBubbleSpringingToTouch = false;
        mIsMovingFromFlinging = true;
        return destinationRelativeX;
    }

    /**
     * Where the stack would be if it were snapped to the nearest horizontal edge (left or right).
     */
    public PointF getStackPositionAlongNearestHorizontalEdge() {
        final PointF stackPos = getStackPosition();
        final boolean onLeft = mLayout.isFirstChildXLeftOfCenter(stackPos.x);
        final RectF bounds = getAllowableStackPositionRegion();

        stackPos.x = onLeft ? bounds.left : bounds.right;
        return stackPos;
    }

    /**
     * Moves the stack in response to rotation. We keep it in the most similar position by keeping
     * it on the same side, and positioning it the same percentage of the way down the screen
     * (taking status bar/nav bar into account by using the allowable region's height).
     */
    public void moveStackToSimilarPositionAfterRotation(boolean wasOnLeft, float verticalPercent) {
        final RectF allowablePos = getAllowableStackPositionRegion();
        final float allowableRegionHeight = allowablePos.bottom - allowablePos.top;

        final float x = wasOnLeft ? allowablePos.left : allowablePos.right;
        final float y = (allowableRegionHeight * verticalPercent) + allowablePos.top;

        setStackPosition(new PointF(x, y));
    }

    /**
     * Flings the first bubble along the given property's axis, using the provided configuration
     * values. When the animation ends - either by hitting the min/max, or by friction sufficiently
     * reducing momentum - a SpringAnimation takes over to snap the bubble to the given final
     * position.
     */
    protected void flingThenSpringFirstBubbleWithStackFollowing(
            DynamicAnimation.ViewProperty property,
            float vel,
            float friction,
            SpringForce spring,
            Float finalPosition) {
        Log.d(TAG, String.format("Flinging %s.",
                        PhysicsAnimationLayout.getReadablePropertyName(property)));

        StackPositionProperty firstBubbleProperty = new StackPositionProperty(property);
        final float currentValue = firstBubbleProperty.getValue(this);
        final RectF bounds = getAllowableStackPositionRegion();
        final float min =
                property.equals(DynamicAnimation.TRANSLATION_X)
                        ? bounds.left
                        : bounds.top;
        final float max =
                property.equals(DynamicAnimation.TRANSLATION_X)
                        ? bounds.right
                        : bounds.bottom;

        FlingAnimation flingAnimation = new FlingAnimation(this, firstBubbleProperty);
        flingAnimation.setFriction(friction)
                .setStartVelocity(vel)

                // If the bubble's property value starts beyond the desired min/max, use that value
                // instead so that the animation won't immediately end. If, for example, the user
                // drags the bubbles into the navigation bar, but then flings them upward, we want
                // the fling to occur despite temporarily having a value outside of the min/max. If
                // the bubbles are out of bounds and flung even farther out of bounds, the fling
                // animation will halt immediately and the SpringAnimation will take over, springing
                // it in reverse to the (legal) final position.
                .setMinValue(Math.min(currentValue, min))
                .setMaxValue(Math.max(currentValue, max))

                .addEndListener((animation, canceled, endValue, endVelocity) -> {
                    if (!canceled) {
                        springFirstBubbleWithStackFollowing(property, spring, endVelocity,
                                finalPosition != null
                                        ? finalPosition
                                        : Math.max(min, Math.min(max, endValue)));
                    }
                });

        cancelStackPositionAnimation(property);
        mStackPositionAnimations.put(property, flingAnimation);
        flingAnimation.start();
    }

    /**
     * Cancel any stack position animations that were started by calling
     * @link #flingThenSpringFirstBubbleWithStackFollowing}, and remove any corresponding end
     * listeners.
     */
    public void cancelStackPositionAnimations() {
        cancelStackPositionAnimation(DynamicAnimation.TRANSLATION_X);
        cancelStackPositionAnimation(DynamicAnimation.TRANSLATION_Y);

        mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_X);
        mLayout.removeEndActionForProperty(DynamicAnimation.TRANSLATION_Y);
    }

    /** Save the current IME height so that we know where the stack bounds should be. */
    public void setImeHeight(int imeHeight) {
        mImeHeight = imeHeight;
    }

    /**
     * Animates the stack either away from the newly visible IME, or back to its original position
     * due to the IME going away.
     */
    public void animateForImeVisibility(boolean imeVisible) {
        final float maxBubbleY = getAllowableStackPositionRegion().bottom;
        float destinationY = Float.MIN_VALUE;

        if (imeVisible) {
            // Stack is lower than it should be and overlaps the now-visible IME.
            if (mStackPosition.y > maxBubbleY && mPreImeY == Float.MIN_VALUE) {
                mPreImeY = mStackPosition.y;
                destinationY = maxBubbleY;
            }
        } else {
            if (mPreImeY > Float.MIN_VALUE) {
                destinationY = mPreImeY;
                mPreImeY = Float.MIN_VALUE;
            }
        }

        if (destinationY > Float.MIN_VALUE) {
            springFirstBubbleWithStackFollowing(
                    DynamicAnimation.TRANSLATION_Y,
                    getSpringForce(DynamicAnimation.TRANSLATION_Y, /* view */ null)
                            .setStiffness(SpringForce.STIFFNESS_LOW),
                    /* startVel */ 0f,
                    destinationY);
        }
    }

    /**
     * Returns the region within which the stack is allowed to rest. This goes slightly off the left
     * and right sides of the screen, below the status bar/cutout and above the navigation bar.
     * While the stack is not allowed to rest outside of these bounds, it can temporarily be
     * animated or dragged beyond them.
     */
    public RectF getAllowableStackPositionRegion() {
        final WindowInsets insets = mLayout.getRootWindowInsets();
        final RectF allowableRegion = new RectF();
        if (insets != null) {
            allowableRegion.left =
                    -mBubbleOffscreen
                            + Math.max(
                            insets.getSystemWindowInsetLeft(),
                            insets.getDisplayCutout() != null
                                    ? insets.getDisplayCutout().getSafeInsetLeft()
                                    : 0);
            allowableRegion.right =
                    mLayout.getWidth()
                            - mIndividualBubbleSize
                            + mBubbleOffscreen
                            - Math.max(
                            insets.getSystemWindowInsetRight(),
                            insets.getDisplayCutout() != null
                                    ? insets.getDisplayCutout().getSafeInsetRight()
                                    : 0);

            allowableRegion.top =
                    mBubblePadding
                            + Math.max(
                            mStatusBarHeight,
                            insets.getDisplayCutout() != null
                                    ? insets.getDisplayCutout().getSafeInsetTop()
                                    : 0);
            allowableRegion.bottom =
                    mLayout.getHeight()
                            - mIndividualBubbleSize
                            - mBubblePadding
                            - (mImeHeight > Float.MIN_VALUE ? mImeHeight + mBubblePadding : 0f)
                            - Math.max(
                            insets.getSystemWindowInsetBottom(),
                            insets.getDisplayCutout() != null
                                    ? insets.getDisplayCutout().getSafeInsetBottom()
                                    : 0);
        }

        return allowableRegion;
    }

    /** Moves the stack in response to a touch event. */
    public void moveStackFromTouch(float x, float y) {

        // If we're springing to the touch point to 'catch up' after dragging out of the dismiss
        // target, then update the stack position animations instead of moving the bubble directly.
        if (mFirstBubbleSpringingToTouch) {
            final SpringAnimation springToTouchX =
                    (SpringAnimation) mStackPositionAnimations.get(DynamicAnimation.TRANSLATION_X);
            final SpringAnimation springToTouchY =
                    (SpringAnimation) mStackPositionAnimations.get(DynamicAnimation.TRANSLATION_Y);

            // If either animation is still running, we haven't caught up. Update the animations.
            if (springToTouchX.isRunning() || springToTouchY.isRunning()) {
                springToTouchX.animateToFinalPosition(x);
                springToTouchY.animateToFinalPosition(y);
            } else {
                // If the animations have finished, the stack is now at the touch point. We can
                // resume moving the bubble directly.
                mFirstBubbleSpringingToTouch = false;
            }
        }

        if (!mFirstBubbleSpringingToTouch && !mWithinDismissTarget) {
            moveFirstBubbleWithStackFollowing(x, y);
        }
    }

    /**
     * Demagnetizes the stack, springing it towards the given point. This also sets flags so that
     * subsequent touch events will update the final position of the demagnetization spring instead
     * of directly moving the bubbles, until demagnetization is complete.
     */
    public void demagnetizeFromDismissToPoint(float x, float y, float velX, float velY) {
        mWithinDismissTarget = false;
        mFirstBubbleSpringingToTouch = true;

        springFirstBubbleWithStackFollowing(
                DynamicAnimation.TRANSLATION_X,
                new SpringForce()
                        .setDampingRatio(DEFAULT_BOUNCINESS)
                        .setStiffness(DEFAULT_STIFFNESS),
                velX, x);

        springFirstBubbleWithStackFollowing(
                DynamicAnimation.TRANSLATION_Y,
                new SpringForce()
                        .setDampingRatio(DEFAULT_BOUNCINESS)
                        .setStiffness(DEFAULT_STIFFNESS),
                velY, y);
    }

    /**
     * Spring the stack towards the dismiss target, respecting existing velocity. This also sets
     * flags so that subsequent touch events will not move the stack until it's demagnetized.
     */
    public void magnetToDismiss(float velX, float velY, float destY, Runnable after) {
        mWithinDismissTarget = true;
        mFirstBubbleSpringingToTouch = false;

        animationForChildAtIndex(0)
                .translationX(mLayout.getWidth() / 2f - mIndividualBubbleSize / 2f)
                .translationY(destY, after)
                .withPositionStartVelocities(velX, velY)
                .withStiffness(SpringForce.STIFFNESS_MEDIUM)
                .withDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
                .start();
    }

    /**
     * 'Implode' the stack by shrinking the bubbles via chained animations and fading them out.
     */
    public void implodeStack(Runnable after) {
        // Pop and fade the bubbles sequentially.
        animationForChildAtIndex(0)
                .scaleX(0.5f)
                .scaleY(0.5f)
                .alpha(0f)
                .withDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)
                .withStiffness(SpringForce.STIFFNESS_HIGH)
                .start(() -> {
                    // Run the callback and reset flags. The child translation animations might
                    // still be running, but that's fine. Once the alpha is at 0f they're no longer
                    // visible anyway.
                    after.run();
                    mWithinDismissTarget = false;
                });
    }

    /**
     * Springs the first bubble to the given final position, with the rest of the stack 'following'.
     */
    protected void springFirstBubbleWithStackFollowing(
            DynamicAnimation.ViewProperty property, SpringForce spring,
            float vel, float finalPosition) {

        if (mLayout.getChildCount() == 0) {
            return;
        }

        Log.d(TAG, String.format("Springing %s to final position %f.",
                PhysicsAnimationLayout.getReadablePropertyName(property),
                finalPosition));

        StackPositionProperty firstBubbleProperty = new StackPositionProperty(property);
        SpringAnimation springAnimation =
                new SpringAnimation(this, firstBubbleProperty)
                        .setSpring(spring)
                        .setStartVelocity(vel);

        cancelStackPositionAnimation(property);
        mStackPositionAnimations.put(property, springAnimation);
        springAnimation.animateToFinalPosition(finalPosition);
    }

    @Override
    Set<DynamicAnimation.ViewProperty> getAnimatedProperties() {
        return Sets.newHashSet(
                DynamicAnimation.TRANSLATION_X, // For positioning.
                DynamicAnimation.TRANSLATION_Y,
                DynamicAnimation.ALPHA,         // For fading in new bubbles.
                DynamicAnimation.SCALE_X,       // For 'popping in' new bubbles.
                DynamicAnimation.SCALE_Y);
    }

    @Override
    int getNextAnimationInChain(DynamicAnimation.ViewProperty property, int index) {
        if (property.equals(DynamicAnimation.TRANSLATION_X)
                || property.equals(DynamicAnimation.TRANSLATION_Y)) {
            return index + 1;
        } else if (mWithinDismissTarget) {
            return index + 1; // Chain all animations in dismiss (scale, alpha, etc. are used).
        } else {
            return NONE;
        }
    }


    @Override
    float getOffsetForChainedPropertyAnimation(DynamicAnimation.ViewProperty property) {
        if (property.equals(DynamicAnimation.TRANSLATION_X)) {
            // If we're in the dismiss target, have the bubbles pile on top of each other with no
            // offset.
            if (mWithinDismissTarget) {
                return 0f;
            } else {
                // Offset to the left if we're on the left, or the right otherwise.
                return mLayout.isFirstChildXLeftOfCenter(mStackPosition.x)
                        ? -mStackOffset : mStackOffset;
            }
        } else {
            return 0f;
        }
    }

    @Override
    SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
        return new SpringForce()
                .setDampingRatio(DEFAULT_BOUNCINESS)
                .setStiffness(mIsMovingFromFlinging ? FLING_FOLLOW_STIFFNESS : DEFAULT_STIFFNESS);
    }

    @Override
    void onChildAdded(View child, int index) {
        if (mLayout.getChildCount() == 1) {
            // If this is the first child added, position the stack in its starting position.
            moveStackToStartPosition();
        } else if (isStackPositionSet() && mLayout.indexOfChild(child) == 0) {
            // Otherwise, animate the bubble in if it's the newest bubble. If we're adding a bubble
            // to the back of the stack, it'll be largely invisible so don't bother animating it in.
            animateInBubble(child);
        }
    }

    @Override
    void onChildRemoved(View child, int index, Runnable finishRemoval) {
        // Animate the removing view in the opposite direction of the stack.
        final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
        animationForChild(child)
                .alpha(0f, finishRemoval /* after */)
                .scaleX(ANIMATE_IN_STARTING_SCALE)
                .scaleY(ANIMATE_IN_STARTING_SCALE)
                .translationX(mStackPosition.x - (-xOffset * ANIMATE_TRANSLATION_FACTOR))
                .start();

        if (mLayout.getChildCount() > 0) {
            animationForChildAtIndex(0).translationX(mStackPosition.x).start();
        } else {
            // Set the start position back to the default since we're out of bubbles. New bubbles
            // will then animate in from the start position.
            mStackPosition = getDefaultStartPosition();
        }
    }

    @Override
    void onChildReordered(View child, int oldIndex, int newIndex) {}

    @Override
    void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
        Resources res = layout.getResources();
        mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
        mIndividualBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
        mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding);
        mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
        mStackStartingVerticalOffset =
                res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
        mStatusBarHeight =
                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
    }

    /** Moves the stack, without any animation, to the starting position. */
    private void moveStackToStartPosition() {
        // Post to ensure that the layout's width and height have been calculated.
        mLayout.setVisibility(View.INVISIBLE);
        mLayout.post(() -> {
            setStackPosition(mRestingStackPosition == null
                    ? getDefaultStartPosition()
                    : mRestingStackPosition);
            mStackMovedToStartPosition = true;
            mLayout.setVisibility(View.VISIBLE);

            // Animate in the top bubble now that we're visible.
            if (mLayout.getChildCount() > 0) {
                animateInBubble(mLayout.getChildAt(0));
            }
        });
    }

    /**
     * Moves the first bubble instantly to the given X or Y translation, and instructs subsequent
     * bubbles to animate 'following' to the new location.
     */
    private void moveFirstBubbleWithStackFollowing(
            DynamicAnimation.ViewProperty property, float value) {

        // Update the canonical stack position.
        if (property.equals(DynamicAnimation.TRANSLATION_X)) {
            mStackPosition.x = value;
        } else if (property.equals(DynamicAnimation.TRANSLATION_Y)) {
            mStackPosition.y = value;
        }

        if (mLayout.getChildCount() > 0) {
            property.setValue(mLayout.getChildAt(0), value);
            if (mLayout.getChildCount() > 1) {
                animationForChildAtIndex(1)
                        .property(property, value + getOffsetForChainedPropertyAnimation(property))
                        .start();
            }
        }
    }

    /** Moves the stack to a position instantly, with no animation. */
    private void setStackPosition(PointF pos) {
        Log.d(TAG, String.format("Setting position to (%f, %f).", pos.x, pos.y));
        mStackPosition.set(pos.x, pos.y);

        // If we're not the active controller, we don't want to physically move the bubble views.
        if (isActiveController()) {
            mLayout.cancelAllAnimations();
            cancelStackPositionAnimations();

            // Since we're not using the chained animations, apply the offsets manually.
            final float xOffset = getOffsetForChainedPropertyAnimation(
                    DynamicAnimation.TRANSLATION_X);
            final float yOffset = getOffsetForChainedPropertyAnimation(
                    DynamicAnimation.TRANSLATION_Y);
            for (int i = 0; i < mLayout.getChildCount(); i++) {
                mLayout.getChildAt(i).setTranslationX(pos.x + (i * xOffset));
                mLayout.getChildAt(i).setTranslationY(pos.y + (i * yOffset));
            }
        }
    }

    /** Returns the default stack position, which is on the top right. */
    private PointF getDefaultStartPosition() {
        return new PointF(
                getAllowableStackPositionRegion().right,
                getAllowableStackPositionRegion().top + mStackStartingVerticalOffset);
    }

    private boolean isStackPositionSet() {
        return mStackMovedToStartPosition;
    }

    /** Animates in the given bubble. */
    private void animateInBubble(View child) {
        if (!isActiveController()) {
            return;
        }

        child.setTranslationY(mStackPosition.y);

        float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
        animationForChild(child)
                .scaleX(ANIMATE_IN_STARTING_SCALE /* from */, 1f /* to */)
                .scaleY(ANIMATE_IN_STARTING_SCALE /* from */, 1f /* to */)
                .alpha(0f /* from */, 1f /* to */)
                .translationX(
                        mStackPosition.x - ANIMATE_TRANSLATION_FACTOR * xOffset /* from */,
                        mStackPosition.x /* to */)
                .start();
    }

    /**
     * Cancels any outstanding first bubble property animations that are running. This does not
     * affect the SpringAnimations controlling the individual bubbles' 'following' effect - it only
     * cancels animations started from {@link #springFirstBubbleWithStackFollowing} and
     * {@link #flingThenSpringFirstBubbleWithStackFollowing}.
     */
    private void cancelStackPositionAnimation(DynamicAnimation.ViewProperty property) {
        if (mStackPositionAnimations.containsKey(property)) {
            mStackPositionAnimations.get(property).cancel();
        }
    }

    /**
     * FloatProperty that uses {@link #moveFirstBubbleWithStackFollowing} to set the first bubble's
     * translation and animate the rest of the stack with it. A DynamicAnimation can animate this
     * property directly to move the first bubble and cause the stack to 'follow' to the new
     * location.
     *
     * This could also be achieved by simply animating the first bubble view and adding an update
     * listener to dispatch movement to the rest of the stack. However, this would require
     * duplication of logic in that update handler - it's simpler to keep all logic contained in the
     * {@link #moveFirstBubbleWithStackFollowing} method.
     */
    private class StackPositionProperty
            extends FloatPropertyCompat<StackAnimationController> {
        private final DynamicAnimation.ViewProperty mProperty;

        private StackPositionProperty(DynamicAnimation.ViewProperty property) {
            super(property.toString());
            mProperty = property;
        }

        @Override
        public float getValue(StackAnimationController controller) {
            return mLayout.getChildCount() > 0 ? mProperty.getValue(mLayout.getChildAt(0)) : 0;
        }

        @Override
        public void setValue(StackAnimationController controller, float value) {
            moveFirstBubbleWithStackFollowing(mProperty, value);
        }
    }
}

