/*
 * 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.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.content.Context;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.FloatProperty;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;

import com.android.systemui.R;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Layout that constructs physics-based animations for each of its children, which behave according
 * to settings provided by a {@link PhysicsAnimationController} instance.
 *
 * See physics-animation-layout.md.
 */
public class PhysicsAnimationLayout extends FrameLayout {
    private static final String TAG = "Bubbs.PAL";

    /**
     * Controls the construction, configuration, and use of the physics animations supplied by this
     * layout.
     */
    abstract static class PhysicsAnimationController {

        /** Configures a given {@link PhysicsPropertyAnimator} for a view at the given index. */
        interface ChildAnimationConfigurator {

            /**
             * Called to configure the animator for the view at the given index.
             *
             * This method should make use of methods such as
             * {@link PhysicsPropertyAnimator#translationX} and
             * {@link PhysicsPropertyAnimator#withStartDelay} to configure the animation.
             *
             * Implementations should not call {@link PhysicsPropertyAnimator#start}, this will
             * happen elsewhere after configuration is complete.
             */
            void configureAnimationForChildAtIndex(int index, PhysicsPropertyAnimator animation);
        }

        /**
         * Returned by {@link #animationsForChildrenFromIndex} to allow starting multiple animations
         * on multiple child views at the same time.
         */
        interface MultiAnimationStarter {

            /**
             * Start all animations and call the given end actions once all animations have
             * completed.
             */
            void startAll(Runnable... endActions);
        }

        /**
         * Constant to return from {@link #getNextAnimationInChain} if the animation should not be
         * chained at all.
         */
        protected static final int NONE = -1;

        /** Set of properties for which the layout should construct physics animations. */
        abstract Set<DynamicAnimation.ViewProperty> getAnimatedProperties();

        /**
         * Returns the index of the next animation after the given index in the animation chain, or
         * {@link #NONE} if it should not be chained, or if the chain should end at the given index.
         *
         * If a next index is returned, an update listener will be added to the animation at the
         * given index that dispatches value updates to the animation at the next index. This
         * creates a 'following' effect.
         *
         * Typical implementations of this method will return either index + 1, or index - 1, to
         * create forward or backward chains between adjacent child views, but this is not required.
         */
        abstract int getNextAnimationInChain(DynamicAnimation.ViewProperty property, int index);

        /**
         * Offsets to be added to the value that chained animations of the given property dispatch
         * to subsequent child animations.
         *
         * This is used for things like maintaining the 'stack' effect in Bubbles, where bubbles
         * stack off to the left or right side slightly.
         */
        abstract float getOffsetForChainedPropertyAnimation(DynamicAnimation.ViewProperty property);

        /**
         * Returns the SpringForce to be used for the given child view's property animation. Despite
         * these usually being similar or identical across properties and views, {@link SpringForce}
         * also contains the SpringAnimation's final position, so we have to construct a new one for
         * each animation rather than using a constant.
         */
        abstract SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view);

        /**
         * Called when a new child is added at the specified index. Controllers can use this
         * opportunity to animate in the new view.
         */
        abstract void onChildAdded(View child, int index);

        /**
         * Called with a child view that has been removed from the layout, from the given index. The
         * passed view has been removed from the layout and added back as a transient view, which
         * renders normally, but is not part of the normal view hierarchy and will not be considered
         * by getChildAt() and getChildCount().
         *
         * The controller can perform animations on the child (either manually, or by using
         * {@link #animationForChild(View)}), and then call finishRemoval when complete.
         *
         * finishRemoval must be called by implementations of this method, or transient views will
         * never be removed.
         */
        abstract void onChildRemoved(View child, int index, Runnable finishRemoval);

        /** Called when a child view has been reordered in the view hierachy. */
        abstract void onChildReordered(View child, int oldIndex, int newIndex);

        /**
         * Called when the controller is set as the active animation controller for the given
         * layout. Once active, the controller can start animations using the animator instances
         * returned by {@link #animationForChild}.
         *
         * While all animations started by the previous controller will be cancelled, the new
         * controller should not make any assumptions about the state of the layout or its children.
         * Their translation, alpha, scale, etc. values may have been changed by the previous
         * controller and should be reset here if relevant.
         */
        abstract void onActiveControllerForLayout(PhysicsAnimationLayout layout);

        protected PhysicsAnimationLayout mLayout;

        PhysicsAnimationController() { }

        /** Whether this controller is the currently active controller for its associated layout. */
        protected boolean isActiveController() {
            return mLayout != null && this == mLayout.mController;
        }

        protected void setLayout(PhysicsAnimationLayout layout) {
            this.mLayout = layout;
            onActiveControllerForLayout(layout);
        }

        protected PhysicsAnimationLayout getLayout() {
            return mLayout;
        }

        /**
         * Returns a {@link PhysicsPropertyAnimator} instance for the given child view.
         */
        protected PhysicsPropertyAnimator animationForChild(View child) {
            PhysicsPropertyAnimator animator =
                    (PhysicsPropertyAnimator) child.getTag(R.id.physics_animator_tag);

            if (animator == null) {
                animator = mLayout.new PhysicsPropertyAnimator(child);
                child.setTag(R.id.physics_animator_tag, animator);
            }

            animator.clearAnimator();
            animator.setAssociatedController(this);

            return animator;
        }

        /** Returns a {@link PhysicsPropertyAnimator} instance for child at the given index. */
        protected PhysicsPropertyAnimator animationForChildAtIndex(int index) {
            return animationForChild(mLayout.getChildAt(index));
        }

        /**
         * Returns a {@link MultiAnimationStarter} whose startAll method will start the physics
         * animations for all children from startIndex onward. The provided configurator will be
         * called with each child's {@link PhysicsPropertyAnimator}, where it can set up each
         * animation appropriately.
         */
        protected MultiAnimationStarter animationsForChildrenFromIndex(
                int startIndex, ChildAnimationConfigurator configurator) {
            final Set<DynamicAnimation.ViewProperty> allAnimatedProperties = new HashSet<>();
            final List<PhysicsPropertyAnimator> allChildAnims = new ArrayList<>();

            // Retrieve the animator for each child, ask the configurator to configure it, then save
            // it and the properties it chose to animate.
            for (int i = startIndex; i < mLayout.getChildCount(); i++) {
                final PhysicsPropertyAnimator anim = animationForChildAtIndex(i);
                configurator.configureAnimationForChildAtIndex(i, anim);
                allAnimatedProperties.addAll(anim.getAnimatedProperties());
                allChildAnims.add(anim);
            }

            // Return a MultiAnimationStarter that will start all of the child animations, and also
            // add a multiple property end listener to the layout that will call the end action
            // provided to startAll() once all animations on the animated properties complete.
            return (endActions) -> {
                final Runnable runAllEndActions = () -> {
                    for (Runnable action : endActions) {
                        action.run();
                    }
                };

                // If there aren't any children to animate, just run the end actions.
                if (mLayout.getChildCount() == 0) {
                    runAllEndActions.run();
                    return;
                }

                if (endActions != null) {
                    setEndActionForMultipleProperties(
                            runAllEndActions,
                            allAnimatedProperties.toArray(
                                    new DynamicAnimation.ViewProperty[0]));
                }

                for (PhysicsPropertyAnimator childAnim : allChildAnims) {
                    childAnim.start();
                }
            };
        }

        /**
         * Sets an end action that will be run when all child animations for a given property have
         * stopped running.
         */
        protected void setEndActionForProperty(
                Runnable action, DynamicAnimation.ViewProperty property) {
            mLayout.mEndActionForProperty.put(property, action);
        }

        /**
         * Sets an end action that will be run when all child animations for all of the given
         * properties have stopped running.
         */
        protected void setEndActionForMultipleProperties(
                Runnable action, DynamicAnimation.ViewProperty... properties) {
            final Runnable checkIfAllFinished = () -> {
                if (!mLayout.arePropertiesAnimating(properties)) {
                    action.run();

                    for (DynamicAnimation.ViewProperty property : properties) {
                        removeEndActionForProperty(property);
                    }
                }
            };

            for (DynamicAnimation.ViewProperty property : properties) {
                setEndActionForProperty(checkIfAllFinished, property);
            }
        }

        /**
         * Removes the end listener that would have been called when all child animations for a
         * given property stopped running.
         */
        protected void removeEndActionForProperty(DynamicAnimation.ViewProperty property) {
            mLayout.mEndActionForProperty.remove(property);
        }
    }

    /**
     * End actions that are called when every child's animation of the given property has finished.
     */
    protected final HashMap<DynamicAnimation.ViewProperty, Runnable> mEndActionForProperty =
            new HashMap<>();

    /** The currently active animation controller. */
    @Nullable protected PhysicsAnimationController mController;

    public PhysicsAnimationLayout(Context context) {
        super(context);
    }

    /**
     * Sets the animation controller and constructs or reconfigures the layout's physics animations
     * to meet the controller's specifications.
     */
    public void setActiveController(PhysicsAnimationController controller) {
        cancelAllAnimations();
        mEndActionForProperty.clear();

        this.mController = controller;
        mController.setLayout(this);

        // Set up animations for this controller's animated properties.
        for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
            setUpAnimationsForProperty(property);
        }
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        addViewInternal(child, index, params, false /* isReorder */);
    }

    @Override
    public void removeView(View view) {
        if (mController != null) {
            final int index = indexOfChild(view);

            // Remove the view and add it back as a transient view so we can animate it out.
            super.removeView(view);
            addTransientView(view, index);

            // Tell the controller to animate this view out, and call the callback when it's
            // finished.
            mController.onChildRemoved(view, index, () -> {
                // The controller says it's done with the transient view, cancel animations in case
                // any are still running and then remove it.
                cancelAnimationsOnView(view);
                removeTransientView(view);
            });
        } else {
            // Without a controller, nobody will animate this view out, so it gets an unceremonious
            // departure.
            super.removeView(view);
        }
    }

    @Override
    public void removeViewAt(int index) {
        removeView(getChildAt(index));
    }

    /** Immediately re-orders the view to the given index. */
    public void reorderView(View view, int index) {
        final int oldIndex = indexOfChild(view);

        super.removeView(view);
        addViewInternal(view, index, view.getLayoutParams(), true /* isReorder */);

        if (mController != null) {
            mController.onChildReordered(view, oldIndex, index);
        }
    }

    /** Checks whether any animations of the given properties are still running. */
    public boolean arePropertiesAnimating(DynamicAnimation.ViewProperty... properties) {
        for (int i = 0; i < getChildCount(); i++) {
            if (arePropertiesAnimatingOnView(getChildAt(i), properties)) {
                return true;
            }
        }

        return false;
    }

    /** Checks whether any animations of the given properties are running on the given view. */
    public boolean arePropertiesAnimatingOnView(
            View view, DynamicAnimation.ViewProperty... properties) {
        final ObjectAnimator targetAnimator = getTargetAnimatorFromView(view);
        for (DynamicAnimation.ViewProperty property : properties) {
            final SpringAnimation animation = getAnimationFromView(property, view);
            if (animation != null && animation.isRunning()) {
                return true;
            }

            // If the target animator is running, its update listener will trigger the translation
            // physics animations at some point. We should consider the translation properties to be
            // be animating in this case, even if the physics animations haven't been started yet.
            final boolean isTranslation =
                    property.equals(DynamicAnimation.TRANSLATION_X)
                            || property.equals(DynamicAnimation.TRANSLATION_Y);
            if (isTranslation && targetAnimator != null && targetAnimator.isRunning()) {
                return true;
            }
        }

        return false;
    }

    /** Cancels all animations that are running on all child views, for all properties. */
    public void cancelAllAnimations() {
        if (mController == null) {
            return;
        }

        cancelAllAnimationsOfProperties(
                mController.getAnimatedProperties().toArray(new DynamicAnimation.ViewProperty[]{}));
    }

    /** Cancels all animations that are running on all child views, for the given properties. */
    public void cancelAllAnimationsOfProperties(DynamicAnimation.ViewProperty... properties) {
        if (mController == null) {
            return;
        }

        for (int i = 0; i < getChildCount(); i++) {
            for (DynamicAnimation.ViewProperty property : properties) {
                final DynamicAnimation anim = getAnimationAtIndex(property, i);
                if (anim != null) {
                    anim.cancel();
                }
            }
        }
    }

    /** Cancels all of the physics animations running on the given view. */
    public void cancelAnimationsOnView(View view) {
        // If present, cancel the target animator so it doesn't restart the translation physics
        // animations.
        final ObjectAnimator targetAnimator = getTargetAnimatorFromView(view);
        if (targetAnimator != null) {
            targetAnimator.cancel();
        }

        // Cancel physics animations on the view.
        for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
            getAnimationFromView(property, view).cancel();
        }
    }

    protected boolean isActiveController(PhysicsAnimationController controller) {
        return mController == controller;
    }

    /** Whether the first child would be left of center if translated to the given x value. */
    protected boolean isFirstChildXLeftOfCenter(float x) {
        if (getChildCount() > 0) {
            return x + (getChildAt(0).getWidth() / 2) < getWidth() / 2;
        } else {
            return false; // If there's no first child, really anything is correct, right?
        }
    }

    /** ViewProperty's toString is useless, this returns a readable name for debug logging. */
    protected static String getReadablePropertyName(DynamicAnimation.ViewProperty property) {
        if (property.equals(DynamicAnimation.TRANSLATION_X)) {
            return "TRANSLATION_X";
        } else if (property.equals(DynamicAnimation.TRANSLATION_Y)) {
            return "TRANSLATION_Y";
        } else if (property.equals(DynamicAnimation.SCALE_X)) {
            return "SCALE_X";
        } else if (property.equals(DynamicAnimation.SCALE_Y)) {
            return "SCALE_Y";
        } else if (property.equals(DynamicAnimation.ALPHA)) {
            return "ALPHA";
        } else {
            return "Unknown animation property.";
        }
    }

    /**
     * Adds a view to the layout. If this addition is not the result of a call to
     * {@link #reorderView}, this will also notify the controller via
     * {@link PhysicsAnimationController#onChildAdded} and set up animations for the view.
     */
    private void addViewInternal(
            View child, int index, ViewGroup.LayoutParams params, boolean isReorder) {
        super.addView(child, index, params);

        // Set up animations for the new view, if the controller is set. If it isn't set, we'll be
        // setting up animations for all children when setActiveController is called.
        if (mController != null && !isReorder) {
            for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
                setUpAnimationForChild(property, child, index);
            }

            mController.onChildAdded(child, index);
        }
    }

    /**
     * Retrieves the animation of the given property from the view at the given index via the view
     * tag system.
     */
    private SpringAnimation getAnimationAtIndex(
            DynamicAnimation.ViewProperty property, int index) {
        return getAnimationFromView(property, getChildAt(index));
    }

    /** Retrieves the animation of the given property from the view via the view tag system. */
    private SpringAnimation getAnimationFromView(
            DynamicAnimation.ViewProperty property, View view) {
        return (SpringAnimation) view.getTag(getTagIdForProperty(property));
    }

    /** Retrieves the target animator from the view via the view tag system. */
    @Nullable private ObjectAnimator getTargetAnimatorFromView(View view) {
        return (ObjectAnimator) view.getTag(R.id.target_animator_tag);
    }

    /** Sets up SpringAnimations of the given property for each child view in the layout. */
    private void setUpAnimationsForProperty(DynamicAnimation.ViewProperty property) {
        for (int i = 0; i < getChildCount(); i++) {
            setUpAnimationForChild(property, getChildAt(i), i);
        }
    }

    /** Constructs a SpringAnimation of the given property for a child view. */
    private void setUpAnimationForChild(
            DynamicAnimation.ViewProperty property, View child, int index) {
        SpringAnimation newAnim = new SpringAnimation(child, property);
        newAnim.addUpdateListener((animation, value, velocity) -> {
            final int indexOfChild = indexOfChild(child);
            final int nextAnimInChain = mController.getNextAnimationInChain(property, indexOfChild);

            if (nextAnimInChain == PhysicsAnimationController.NONE || indexOfChild < 0) {
                return;
            }

            final float offset = mController.getOffsetForChainedPropertyAnimation(property);
            if (nextAnimInChain < getChildCount()) {
                getAnimationAtIndex(property, nextAnimInChain)
                        .animateToFinalPosition(value + offset);
            }
        });

        newAnim.setSpring(mController.getSpringForce(property, child));
        newAnim.addEndListener(new AllAnimationsForPropertyFinishedEndListener(property));
        child.setTag(getTagIdForProperty(property), newAnim);
    }

    /** Return a stable ID to use as a tag key for the given property's animations. */
    private int getTagIdForProperty(DynamicAnimation.ViewProperty property) {
        if (property.equals(DynamicAnimation.TRANSLATION_X)) {
            return R.id.translation_x_dynamicanimation_tag;
        } else if (property.equals(DynamicAnimation.TRANSLATION_Y)) {
            return R.id.translation_y_dynamicanimation_tag;
        } else if (property.equals(DynamicAnimation.SCALE_X)) {
            return R.id.scale_x_dynamicanimation_tag;
        } else if (property.equals(DynamicAnimation.SCALE_Y)) {
            return R.id.scale_y_dynamicanimation_tag;
        } else if (property.equals(DynamicAnimation.ALPHA)) {
            return R.id.alpha_dynamicanimation_tag;
        }

        return -1;
    }

    /**
     * End listener that is added to each individual DynamicAnimation, which dispatches to a single
     * listener when every other animation of the given property is no longer running.
     *
     * This is required since chained DynamicAnimations can stop and start again due to changes in
     * upstream animations. This means that adding an end listener to just the last animation is not
     * sufficient. By firing only when every other animation on the property has stopped running, we
     * ensure that no animation will be restarted after the single end listener is called.
     */
    protected class AllAnimationsForPropertyFinishedEndListener
            implements DynamicAnimation.OnAnimationEndListener {
        private DynamicAnimation.ViewProperty mProperty;

        AllAnimationsForPropertyFinishedEndListener(DynamicAnimation.ViewProperty property) {
            this.mProperty = property;
        }

        @Override
        public void onAnimationEnd(
                DynamicAnimation anim, boolean canceled, float value, float velocity) {
            if (!arePropertiesAnimating(mProperty)) {
                if (mEndActionForProperty.containsKey(mProperty)) {
                    final Runnable callback = mEndActionForProperty.get(mProperty);

                    if (callback != null) {
                        callback.run();
                    }
                }
            }
        }
    }

    /**
     * Animator class returned by {@link PhysicsAnimationController#animationForChild}, to allow
     * controllers to animate child views using physics animations.
     *
     * See docs/physics-animation-layout.md for documentation and examples.
     */
    protected class PhysicsPropertyAnimator {
        /** The view whose properties this animator animates. */
        private View mView;

        /** Start velocity to use for all property animations. */
        private float mDefaultStartVelocity = -Float.MAX_VALUE;

        /** Start delay to use when start is called. */
        private long mStartDelay = 0;

        /** Damping ratio to use for the animations. */
        private float mDampingRatio = -1;

        /** Stiffness to use for the animations. */
        private float mStiffness = -1;

        /** End actions to call when animations for the given property complete. */
        private Map<DynamicAnimation.ViewProperty, Runnable[]> mEndActionsForProperty =
                new HashMap<>();

        /**
         * Start velocities to use for TRANSLATION_X and TRANSLATION_Y, since these are often
         * provided by VelocityTrackers and differ from each other.
         */
        private Map<DynamicAnimation.ViewProperty, Float> mPositionStartVelocities =
                new HashMap<>();

        /**
         * End actions to call when both TRANSLATION_X and TRANSLATION_Y animations have completed,
         * if {@link #position} was used to animate TRANSLATION_X and TRANSLATION_Y simultaneously.
         */
        @Nullable private Runnable[] mPositionEndActions;

        /**
         * All of the properties that have been set and will animate when {@link #start} is called.
         */
        private Map<DynamicAnimation.ViewProperty, Float> mAnimatedProperties = new HashMap<>();

        /**
         * All of the initial property values that have been set. These values will be instantly set
         * when {@link #start} is called, just before the animation begins.
         */
        private Map<DynamicAnimation.ViewProperty, Float> mInitialPropertyValues = new HashMap<>();

        /** The animation controller that last retrieved this animator instance. */
        private PhysicsAnimationController mAssociatedController;

        /**
         * Animator used to traverse the path provided to {@link #followAnimatedTargetAlongPath}. As
         * the path is traversed, the view's translation spring animation final positions are
         * updated such that the view 'follows' the current position on the path.
         */
        @Nullable private ObjectAnimator mPathAnimator;

        /** Current position on the path. This is animated by {@link #mPathAnimator}. */
        private PointF mCurrentPointOnPath = new PointF();

        /**
         * FloatProperty instances that can be passed to {@link ObjectAnimator} to animate the value
         * of {@link #mCurrentPointOnPath}.
         */
        private final FloatProperty<PhysicsPropertyAnimator> mCurrentPointOnPathXProperty =
                new FloatProperty<PhysicsPropertyAnimator>("PathX") {
            @Override
            public void setValue(PhysicsPropertyAnimator object, float value) {
                mCurrentPointOnPath.x = value;
            }

            @Override
            public Float get(PhysicsPropertyAnimator object) {
                return mCurrentPointOnPath.x;
            }
        };

        private final FloatProperty<PhysicsPropertyAnimator> mCurrentPointOnPathYProperty =
                new FloatProperty<PhysicsPropertyAnimator>("PathY") {
            @Override
            public void setValue(PhysicsPropertyAnimator object, float value) {
                mCurrentPointOnPath.y = value;
            }

            @Override
            public Float get(PhysicsPropertyAnimator object) {
                return mCurrentPointOnPath.y;
            }
        };

        protected PhysicsPropertyAnimator(View view) {
            this.mView = view;
        }

        /** Animate a property to the given value, then call the optional end actions. */
        public PhysicsPropertyAnimator property(
                DynamicAnimation.ViewProperty property, float value, Runnable... endActions) {
            mAnimatedProperties.put(property, value);
            mEndActionsForProperty.put(property, endActions);
            return this;
        }

        /** Animate the view's alpha value to the provided value. */
        public PhysicsPropertyAnimator alpha(float alpha, Runnable... endActions) {
            return property(DynamicAnimation.ALPHA, alpha, endActions);
        }

        /** Set the view's alpha value to 'from', then animate it to the given value. */
        public PhysicsPropertyAnimator alpha(float from, float to, Runnable... endActions) {
            mInitialPropertyValues.put(DynamicAnimation.ALPHA, from);
            return alpha(to, endActions);
        }

        /** Animate the view's translationX value to the provided value. */
        public PhysicsPropertyAnimator translationX(float translationX, Runnable... endActions) {
            mPathAnimator = null; // We aren't using the path anymore if we're translating.
            return property(DynamicAnimation.TRANSLATION_X, translationX, endActions);
        }

        /** Set the view's translationX value to 'from', then animate it to the given value. */
        public PhysicsPropertyAnimator translationX(
                float from, float to, Runnable... endActions) {
            mInitialPropertyValues.put(DynamicAnimation.TRANSLATION_X, from);
            return translationX(to, endActions);
        }

        /** Animate the view's translationY value to the provided value. */
        public PhysicsPropertyAnimator translationY(float translationY, Runnable... endActions) {
            mPathAnimator = null; // We aren't using the path anymore if we're translating.
            return property(DynamicAnimation.TRANSLATION_Y, translationY, endActions);
        }

        /** Set the view's translationY value to 'from', then animate it to the given value. */
        public PhysicsPropertyAnimator translationY(
                float from, float to, Runnable... endActions) {
            mInitialPropertyValues.put(DynamicAnimation.TRANSLATION_Y, from);
            return translationY(to, endActions);
        }

        /**
         * Animate the view's translationX and translationY values, and call the end actions only
         * once both TRANSLATION_X and TRANSLATION_Y animations have completed.
         */
        public PhysicsPropertyAnimator position(
                float translationX, float translationY, Runnable... endActions) {
            mPositionEndActions = endActions;
            translationX(translationX);
            return translationY(translationY);
        }

        /**
         * Animates a 'target' point that moves along the given path, using the provided duration
         * and interpolator to animate the target. The view itself is animated using physics-based
         * animations, whose final positions are updated to the target position as it animates. This
         * results in the view 'following' the target in a realistic way.
         *
         * This method will override earlier calls to {@link #translationX}, {@link #translationY},
         * or {@link #position}, ultimately animating the view's position to the final point on the
         * given path.
         *
         * Any provided end listeners will be called when the physics-based animations kicked off by
         * the moving target have completed - not when the target animation completes.
         */
        public PhysicsPropertyAnimator followAnimatedTargetAlongPath(
                Path path,
                int targetAnimDuration,
                TimeInterpolator targetAnimInterpolator,
                Runnable... endActions) {
            mPathAnimator = ObjectAnimator.ofFloat(
                    this, mCurrentPointOnPathXProperty, mCurrentPointOnPathYProperty, path);
            mPathAnimator.setDuration(targetAnimDuration);
            mPathAnimator.setInterpolator(targetAnimInterpolator);

            mPositionEndActions = endActions;

            // Remove translation related values since we're going to ignore them and follow the
            // path instead.
            clearTranslationValues();
            return this;
        }

        private void clearTranslationValues() {
            mAnimatedProperties.remove(DynamicAnimation.TRANSLATION_X);
            mAnimatedProperties.remove(DynamicAnimation.TRANSLATION_Y);
            mInitialPropertyValues.remove(DynamicAnimation.TRANSLATION_X);
            mInitialPropertyValues.remove(DynamicAnimation.TRANSLATION_Y);
            mEndActionForProperty.remove(DynamicAnimation.TRANSLATION_X);
            mEndActionForProperty.remove(DynamicAnimation.TRANSLATION_Y);
        }

        /** Animate the view's scaleX value to the provided value. */
        public PhysicsPropertyAnimator scaleX(float scaleX, Runnable... endActions) {
            return property(DynamicAnimation.SCALE_X, scaleX, endActions);
        }

        /** Set the view's scaleX value to 'from', then animate it to the given value. */
        public PhysicsPropertyAnimator scaleX(float from, float to, Runnable... endActions) {
            mInitialPropertyValues.put(DynamicAnimation.SCALE_X, from);
            return scaleX(to, endActions);
        }

        /** Animate the view's scaleY value to the provided value. */
        public PhysicsPropertyAnimator scaleY(float scaleY, Runnable... endActions) {
            return property(DynamicAnimation.SCALE_Y, scaleY, endActions);
        }

        /** Set the view's scaleY value to 'from', then animate it to the given value. */
        public PhysicsPropertyAnimator scaleY(float from, float to, Runnable... endActions) {
            mInitialPropertyValues.put(DynamicAnimation.SCALE_Y, from);
            return scaleY(to, endActions);
        }

        /** Set the start velocity to use for all property animations. */
        public PhysicsPropertyAnimator withStartVelocity(float startVel) {
            mDefaultStartVelocity = startVel;
            return this;
        }

        /**
         * Set the damping ratio to use for this animation. If not supplied, will default to the
         * value from {@link PhysicsAnimationController#getSpringForce}.
         */
        public PhysicsPropertyAnimator withDampingRatio(float dampingRatio) {
            mDampingRatio = dampingRatio;
            return this;
        }

        /**
         * Set the stiffness to use for this animation. If not supplied, will default to the
         * value from {@link PhysicsAnimationController#getSpringForce}.
         */
        public PhysicsPropertyAnimator withStiffness(float stiffness) {
            mStiffness = stiffness;
            return this;
        }

        /**
         * Set the start velocities to use for TRANSLATION_X and TRANSLATION_Y animations. This
         * overrides any value set via {@link #withStartVelocity(float)} for those properties.
         */
        public PhysicsPropertyAnimator withPositionStartVelocities(float velX, float velY) {
            mPositionStartVelocities.put(DynamicAnimation.TRANSLATION_X, velX);
            mPositionStartVelocities.put(DynamicAnimation.TRANSLATION_Y, velY);
            return this;
        }

        /** Set a delay, in milliseconds, before kicking off the animations. */
        public PhysicsPropertyAnimator withStartDelay(long startDelay) {
            mStartDelay = startDelay;
            return this;
        }

        /**
         * Start the animations, and call the optional end actions once all animations for every
         * animated property on every child (including chained animations) have ended.
         */
        public void start(Runnable... after) {
            if (!isActiveController(mAssociatedController)) {
                Log.w(TAG, "Only the active animation controller is allowed to start animations. "
                        + "Use PhysicsAnimationLayout#setActiveController to set the active "
                        + "animation controller.");
                return;
            }

            final Set<DynamicAnimation.ViewProperty> properties = getAnimatedProperties();

            // If there are end actions, set an end listener on the layout for all the properties
            // we're about to animate.
            if (after != null && after.length > 0) {
                final DynamicAnimation.ViewProperty[] propertiesArray =
                        properties.toArray(new DynamicAnimation.ViewProperty[0]);
                mAssociatedController.setEndActionForMultipleProperties(() -> {
                    for (Runnable callback : after) {
                        callback.run();
                    }
                }, propertiesArray);
            }

            // If we used position-specific end actions, we'll need to listen for both TRANSLATION_X
            // and TRANSLATION_Y animations ending, and call them once both have finished.
            if (mPositionEndActions != null) {
                final SpringAnimation translationXAnim =
                        getAnimationFromView(DynamicAnimation.TRANSLATION_X, mView);
                final SpringAnimation translationYAnim =
                        getAnimationFromView(DynamicAnimation.TRANSLATION_Y, mView);
                final Runnable waitForBothXAndY = () -> {
                    if (!translationXAnim.isRunning() && !translationYAnim.isRunning()) {
                        if (mPositionEndActions != null) {
                            for (Runnable callback : mPositionEndActions) {
                                callback.run();
                            }
                        }

                        mPositionEndActions = null;
                    }
                };

                mEndActionsForProperty.put(DynamicAnimation.TRANSLATION_X,
                        new Runnable[]{waitForBothXAndY});
                mEndActionsForProperty.put(DynamicAnimation.TRANSLATION_Y,
                        new Runnable[]{waitForBothXAndY});
            }

            if (mPathAnimator != null) {
                startPathAnimation();
            }

            // Actually start the animations.
            for (DynamicAnimation.ViewProperty property : properties) {
                // Don't start translation animations if we're using a path animator, the update
                // listeners added to that animator will take care of that.
                if (mPathAnimator != null
                        && (property.equals(DynamicAnimation.TRANSLATION_X)
                            || property.equals(DynamicAnimation.TRANSLATION_Y))) {
                    return;
                }

                if (mInitialPropertyValues.containsKey(property)) {
                    property.setValue(mView, mInitialPropertyValues.get(property));
                }

                final SpringForce defaultSpringForce = mController.getSpringForce(property, mView);
                animateValueForChild(
                        property,
                        mView,
                        mAnimatedProperties.get(property),
                        mPositionStartVelocities.getOrDefault(property, mDefaultStartVelocity),
                        mStartDelay,
                        mStiffness >= 0 ? mStiffness : defaultSpringForce.getStiffness(),
                        mDampingRatio >= 0 ? mDampingRatio : defaultSpringForce.getDampingRatio(),
                        mEndActionsForProperty.get(property));
            }

            clearAnimator();
        }

        /** Returns the set of properties that will animate once {@link #start} is called. */
        protected Set<DynamicAnimation.ViewProperty> getAnimatedProperties() {
            final HashSet<DynamicAnimation.ViewProperty> animatedProperties = new HashSet<>(
                    mAnimatedProperties.keySet());

            // If we're using a path animator, it'll kick off translation animations.
            if (mPathAnimator != null) {
                animatedProperties.add(DynamicAnimation.TRANSLATION_X);
                animatedProperties.add(DynamicAnimation.TRANSLATION_Y);
            }

            return animatedProperties;
        }

        /**
         * Animates the property of the given child view, then runs the callback provided when the
         * animation ends.
         */
        protected void animateValueForChild(
                DynamicAnimation.ViewProperty property,
                View view,
                float value,
                float startVel,
                long startDelay,
                float stiffness,
                float dampingRatio,
                Runnable... afterCallbacks) {
            if (view != null) {
                final SpringAnimation animation =
                        (SpringAnimation) view.getTag(getTagIdForProperty(property));
                if (afterCallbacks != null) {
                    animation.addEndListener(new OneTimeEndListener() {
                        @Override
                        public void onAnimationEnd(DynamicAnimation animation, boolean canceled,
                                float value, float velocity) {
                            super.onAnimationEnd(animation, canceled, value, velocity);
                            for (Runnable runnable : afterCallbacks) {
                                runnable.run();
                            }
                        }
                    });
                }

                final SpringForce animationSpring = animation.getSpring();

                if (animationSpring == null) {
                    return;
                }

                final Runnable configureAndStartAnimation = () -> {
                    animationSpring.setStiffness(stiffness);
                    animationSpring.setDampingRatio(dampingRatio);

                    if (startVel > -Float.MAX_VALUE) {
                        animation.setStartVelocity(startVel);
                    }

                    animationSpring.setFinalPosition(value);
                    animation.start();
                };

                if (startDelay > 0) {
                    postDelayed(configureAndStartAnimation, startDelay);
                } else {
                    configureAndStartAnimation.run();
                }
            }
        }

        /**
         * Updates the final position of a view's animation, without changing any of the animation's
         * other settings. Calling this before an initial call to {@link #animateValueForChild} will
         * work, but result in unknown values for stiffness, etc. and is not recommended.
         */
        private void updateValueForChild(
                DynamicAnimation.ViewProperty property, View view, float position) {
            if (view != null) {
                final SpringAnimation animation =
                        (SpringAnimation) view.getTag(getTagIdForProperty(property));
                final SpringForce animationSpring = animation.getSpring();

                if (animationSpring == null) {
                    return;
                }

                animationSpring.setFinalPosition(position);
                animation.start();
            }
        }

        /**
         * Configures the path animator to respect the settings passed into the animation builder
         * and adds update listeners that update the translation physics animations. Then, starts
         * the path animation.
         */
        protected void startPathAnimation() {
            final SpringForce defaultSpringForceX = mController.getSpringForce(
                    DynamicAnimation.TRANSLATION_X, mView);
            final SpringForce defaultSpringForceY = mController.getSpringForce(
                    DynamicAnimation.TRANSLATION_Y, mView);

            if (mStartDelay > 0) {
                mPathAnimator.setStartDelay(mStartDelay);
            }

            final Runnable updatePhysicsAnims = () -> {
                updateValueForChild(
                        DynamicAnimation.TRANSLATION_X, mView, mCurrentPointOnPath.x);
                updateValueForChild(
                        DynamicAnimation.TRANSLATION_Y, mView, mCurrentPointOnPath.y);
            };

            mPathAnimator.addUpdateListener(pathAnim -> updatePhysicsAnims.run());
            mPathAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    animateValueForChild(
                            DynamicAnimation.TRANSLATION_X,
                            mView,
                            mCurrentPointOnPath.x,
                            mDefaultStartVelocity,
                            0 /* startDelay */,
                            mStiffness >= 0 ? mStiffness : defaultSpringForceX.getStiffness(),
                            mDampingRatio >= 0
                                    ? mDampingRatio
                                    : defaultSpringForceX.getDampingRatio());

                    animateValueForChild(
                            DynamicAnimation.TRANSLATION_Y,
                            mView,
                            mCurrentPointOnPath.y,
                            mDefaultStartVelocity,
                            0 /* startDelay */,
                            mStiffness >= 0 ? mStiffness : defaultSpringForceY.getStiffness(),
                            mDampingRatio >= 0
                                    ? mDampingRatio
                                    : defaultSpringForceY.getDampingRatio());
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    updatePhysicsAnims.run();
                }
            });

            // If there's a target animator saved for the view, make sure it's not running.
            final ObjectAnimator targetAnimator = getTargetAnimatorFromView(mView);
            if (targetAnimator != null) {
                targetAnimator.cancel();
            }

            mView.setTag(R.id.target_animator_tag, mPathAnimator);
            mPathAnimator.start();
        }

        private void clearAnimator() {
            mInitialPropertyValues.clear();
            mAnimatedProperties.clear();
            mPositionStartVelocities.clear();
            mDefaultStartVelocity = -Float.MAX_VALUE;
            mStartDelay = 0;
            mStiffness = -1;
            mDampingRatio = -1;
            mEndActionsForProperty.clear();
            mPathAnimator = null;
            mPositionEndActions = null;
        }

        /**
         * Sets the controller that last retrieved this animator instance, so that we can prevent
         * {@link #start} from actually starting animations if called by a non-active controller.
         */
        private void setAssociatedController(PhysicsAnimationController controller) {
            mAssociatedController = controller;
        }
    }

    @Override
    protected boolean canReceivePointerEvents() {
        return false;
    }
}
