/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.support.animation;

import android.os.Looper;
import android.support.annotation.FloatRange;
import android.support.v4.view.ViewCompat;
import android.util.AndroidRuntimeException;
import android.view.View;

import java.util.ArrayList;

/**
 * This class is the base class of physics-based animations. It manages the animation's
 * lifecycle such as {@link #start()} and {@link #cancel()}. This base class also handles the common
 * setup for all the subclass animations. For example, DynamicAnimation supports adding
 * {@link OnAnimationEndListener} and {@link OnAnimationUpdateListener} so that the important
 * animation events can be observed through the callbacks. The start conditions for any subclass of
 * DynamicAnimation can be set using {@link #setStartValue(float)} and
 * {@link #setStartVelocity(float)}.
 *
 * @param <T> subclass of DynamicAnimation
 */
public abstract class DynamicAnimation<T extends DynamicAnimation<T>>
        implements AnimationHandler.AnimationFrameCallback {

    /**
     * ViewProperty holds the access of a property of a {@link View}. When an animation is
     * created with a {@link ViewProperty} instance, the corresponding property value of the view
     * will be updated through this ViewProperty instance.
     */
    public abstract static class ViewProperty extends FloatPropertyCompat<View> {
        private ViewProperty(String name) {
            super(name);
        }
    }

    /**
     * View's translationX property.
     */
    public static final ViewProperty TRANSLATION_X = new ViewProperty("translationX") {
        @Override
        public void setValue(View view, float value) {
            view.setTranslationX(value);
        }

        @Override
        public float getValue(View view) {
            return view.getTranslationX();
        }
    };

    /**
     * View's translationY property.
     */
    public static final ViewProperty TRANSLATION_Y = new ViewProperty("translationY") {
        @Override
        public void setValue(View view, float value) {
            view.setTranslationY(value);
        }

        @Override
        public float getValue(View view) {
            return view.getTranslationY();
        }
    };

    /**
     * View's translationZ property.
     */
    public static final ViewProperty TRANSLATION_Z = new ViewProperty("translationZ") {
        @Override
        public void setValue(View view, float value) {
            ViewCompat.setTranslationZ(view, value);
        }

        @Override
        public float getValue(View view) {
            return ViewCompat.getTranslationZ(view);
        }
    };

    /**
     * View's scaleX property.
     */
    public static final ViewProperty SCALE_X = new ViewProperty("scaleX") {
        @Override
        public void setValue(View view, float value) {
            view.setScaleX(value);
        }

        @Override
        public float getValue(View view) {
            return view.getScaleX();
        }
    };

    /**
     * View's scaleY property.
     */
    public static final ViewProperty SCALE_Y = new ViewProperty("scaleY") {
        @Override
        public void setValue(View view, float value) {
            view.setScaleY(value);
        }

        @Override
        public float getValue(View view) {
            return view.getScaleY();
        }
    };

    /**
     * View's rotation property.
     */
    public static final ViewProperty ROTATION = new ViewProperty("rotation") {
        @Override
        public void setValue(View view, float value) {
            view.setRotation(value);
        }

        @Override
        public float getValue(View view) {
            return view.getRotation();
        }
    };

    /**
     * View's rotationX property.
     */
    public static final ViewProperty ROTATION_X = new ViewProperty("rotationX") {
        @Override
        public void setValue(View view, float value) {
            view.setRotationX(value);
        }

        @Override
        public float getValue(View view) {
            return view.getRotationX();
        }
    };

    /**
     * View's rotationY property.
     */
    public static final ViewProperty ROTATION_Y = new ViewProperty("rotationY") {
        @Override
        public void setValue(View view, float value) {
            view.setRotationY(value);
        }

        @Override
        public float getValue(View view) {
            return view.getRotationY();
        }
    };

    /**
     * View's x property.
     */
    public static final ViewProperty X = new ViewProperty("x") {
        @Override
        public void setValue(View view, float value) {
            view.setX(value);
        }

        @Override
        public float getValue(View view) {
            return view.getX();
        }
    };

    /**
     * View's y property.
     */
    public static final ViewProperty Y = new ViewProperty("y") {
        @Override
        public void setValue(View view, float value) {
            view.setY(value);
        }

        @Override
        public float getValue(View view) {
            return view.getY();
        }
    };

    /**
     * View's z property.
     */
    public static final ViewProperty Z = new ViewProperty("z") {
        @Override
        public void setValue(View view, float value) {
            ViewCompat.setZ(view, value);
        }

        @Override
        public float getValue(View view) {
            return ViewCompat.getZ(view);
        }
    };

    /**
     * View's alpha property.
     */
    public static final ViewProperty ALPHA = new ViewProperty("alpha") {
        @Override
        public void setValue(View view, float value) {
            view.setAlpha(value);
        }

        @Override
        public float getValue(View view) {
            return view.getAlpha();
        }
    };

    // Properties below are not RenderThread compatible
    /**
     * View's scrollX property.
     */
    public static final ViewProperty SCROLL_X = new ViewProperty("scrollX") {
        @Override
        public void setValue(View view, float value) {
            view.setScrollX((int) value);
        }

        @Override
        public float getValue(View view) {
            return view.getScrollX();
        }
    };

    /**
     * View's scrollY property.
     */
    public static final ViewProperty SCROLL_Y = new ViewProperty("scrollY") {
        @Override
        public void setValue(View view, float value) {
            view.setScrollY((int) value);
        }

        @Override
        public float getValue(View view) {
            return view.getScrollY();
        }
    };

    /**
     * The minimum visible change in pixels that can be visible to users.
     */
    public static final float MIN_VISIBLE_CHANGE_PIXELS = 1f;
    /**
     * The minimum visible change in degrees that can be visible to users.
     */
    public static final float MIN_VISIBLE_CHANGE_ROTATION_DEGREES = 1f / 10f;
    /**
     * The minimum visible change in alpha that can be visible to users.
     */
    public static final float MIN_VISIBLE_CHANGE_ALPHA = 1f / 256f;
    /**
     * The minimum visible change in scale that can be visible to users.
     */
    public static final float MIN_VISIBLE_CHANGE_SCALE = 1f / 500f;

    // Use the max value of float to indicate an unset state.
    private static final float UNSET = Float.MAX_VALUE;

    // Multiplier to the min visible change value for value threshold
    private static final float THRESHOLD_MULTIPLIER = 0.75f;

    // Internal tracking for velocity.
    float mVelocity = 0;

    // Internal tracking for value.
    float mValue = UNSET;

    // Tracks whether start value is set. If not, the animation will obtain the value at the time
    // of starting through the getter and use that as the starting value of the animation.
    boolean mStartValueIsSet = false;

    // Target to be animated.
    final Object mTarget;

    // View property id.
    final FloatPropertyCompat mProperty;

    // Package private tracking of animation lifecycle state. Visible to subclass animations.
    boolean mRunning = false;

    // Min and max values that defines the range of the animation values.
    float mMaxValue = Float.MAX_VALUE;
    float mMinValue = -mMaxValue;

    // Last frame time. Always gets reset to -1  at the end of the animation.
    private long mLastFrameTime = 0;

    private float mMinVisibleChange;

    // List of end listeners
    private final ArrayList<OnAnimationEndListener> mEndListeners = new ArrayList<>();

    // List of update listeners
    private final ArrayList<OnAnimationUpdateListener> mUpdateListeners = new ArrayList<>();

    // Internal state for value/velocity pair.
    static class MassState {
        float mValue;
        float mVelocity;
    }

    /**
     * Creates a dynamic animation with the given FloatValueHolder instance.
     *
     * @param floatValueHolder the FloatValueHolder instance to be animated.
     */
    DynamicAnimation(final FloatValueHolder floatValueHolder) {
        mTarget = null;
        mProperty = new FloatPropertyCompat("FloatValueHolder") {
            @Override
            public float getValue(Object object) {
                return floatValueHolder.getValue();
            }

            @Override
            public void setValue(Object object, float value) {
                floatValueHolder.setValue(value);
            }
        };
        mMinVisibleChange = MIN_VISIBLE_CHANGE_PIXELS;
    }

    /**
     * Creates a dynamic animation to animate the given property for the given {@link View}
     *
     * @param object the Object whose property is to be animated
     * @param property the property to be animated
     */

    <K> DynamicAnimation(K object, FloatPropertyCompat<K> property) {
        mTarget = object;
        mProperty = property;
        if (mProperty == ROTATION || mProperty == ROTATION_X
                || mProperty == ROTATION_Y) {
            mMinVisibleChange = MIN_VISIBLE_CHANGE_ROTATION_DEGREES;
        } else if (mProperty == ALPHA) {
            mMinVisibleChange = MIN_VISIBLE_CHANGE_ALPHA;
        } else if (mProperty == SCALE_X || mProperty == SCALE_Y) {
            mMinVisibleChange = MIN_VISIBLE_CHANGE_ALPHA;
        } else {
            mMinVisibleChange = MIN_VISIBLE_CHANGE_PIXELS;
        }
    }

    /**
     * Sets the start value of the animation. If start value is not set, the animation will get
     * the current value for the view's property, and use that as the start value.
     *
     * @param startValue start value for the animation
     * @return the Animation whose start value is being set
     */
    public T setStartValue(float startValue) {
        mValue = startValue;
        mStartValueIsSet = true;
        return (T) this;
    }

    /**
     * Start velocity of the animation. Default velocity is 0. Unit: change in property per
     * second (e.g. pixels per second, scale/alpha value change per second).
     *
     * <p>Note when using a fixed value as the start velocity (as opposed to getting the velocity
     * through touch events), it is recommended to define such a value in dp/second and convert it
     * to pixel/second based on the density of the screen to achieve a consistent look across
     * different screens.
     *
     * <p>To convert from dp/second to pixel/second:
     * <pre class="prettyprint">
     * float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond,
     *         getResources().getDisplayMetrics());
     * </pre>
     *
     * @param startVelocity start velocity of the animation
     * @return the Animation whose start velocity is being set
     */
    public T setStartVelocity(float startVelocity) {
        mVelocity = startVelocity;
        return (T) this;
    }

    /**
     * Sets the max value of the animation. Animations will not animate beyond their max value.
     * Whether or not animation will come to an end when max value is reached is dependent on the
     * child animation's implementation.
     *
     * @param max maximum value of the property to be animated
     * @return the Animation whose max value is being set
     */
    public T setMaxValue(float max) {
        // This max value should be checked and handled in the subclass animations, instead of
        // assuming the end of the animations when the max/min value is hit in the base class.
        // The reason is that hitting max/min value may just be a transient state, such as during
        // the spring oscillation.
        mMaxValue = max;
        return (T) this;
    }

    /**
     * Sets the min value of the animation. Animations will not animate beyond their min value.
     * Whether or not animation will come to an end when min value is reached is dependent on the
     * child animation's implementation.
     *
     * @param min minimum value of the property to be animated
     * @return the Animation whose min value is being set
     */
    public T setMinValue(float min) {
        mMinValue = min;
        return (T) this;
    }

    /**
     * Adds an end listener to the animation for receiving onAnimationEnd callbacks. If the listener
     * is {@code null} or has already been added to the list of listeners for the animation, no op.
     *
     * @param listener the listener to be added
     * @return the animation to which the listener is added
     */
    public T addEndListener(OnAnimationEndListener listener) {
        if (!mEndListeners.contains(listener)) {
            mEndListeners.add(listener);
        }
        return (T) this;
    }

    /**
     * Removes the end listener from the animation, so as to stop receiving animation end callbacks.
     *
     * @param listener the listener to be removed
     */
    public void removeEndListener(OnAnimationEndListener listener) {
        removeEntry(mEndListeners, listener);
    }

    /**
     * Adds an update listener to the animation for receiving per-frame animation update callbacks.
     * If the listener is {@code null} or has already been added to the list of listeners for the
     * animation, no op.
     *
     * <p>Note that update listener should only be added before the start of the animation.
     *
     * @param listener the listener to be added
     * @return the animation to which the listener is added
     * @throws UnsupportedOperationException if the update listener is added after the animation has
     *                                       started
     */
    public T addUpdateListener(OnAnimationUpdateListener listener) {
        if (isRunning()) {
            // Require update listener to be added before the animation, such as when we start
            // the animation, we know whether the animation is RenderThread compatible.
            throw new UnsupportedOperationException("Error: Update listeners must be added before"
                    + "the animation.");
        }
        if (!mUpdateListeners.contains(listener)) {
            mUpdateListeners.add(listener);
        }
        return (T) this;
    }

    /**
     * Removes the update listener from the animation, so as to stop receiving animation update
     * callbacks.
     *
     * @param listener the listener to be removed
     */
    public void removeUpdateListener(OnAnimationUpdateListener listener) {
        removeEntry(mUpdateListeners, listener);
    }


    /**
     * This method sets the minimal change of animation value that is visible to users, which helps
     * determine a reasonable threshold for the animation's termination condition. It is critical
     * to set the minimal visible change for custom properties (i.e. non-<code>ViewProperty</code>s)
     * unless the custom property is in pixels.
     *
     * <p>For custom properties, this minimum visible change defaults to change in pixel
     * (i.e. {@link #MIN_VISIBLE_CHANGE_PIXELS}. It is recommended to adjust this value that is
     * reasonable for the property to be animated. A general rule of thumb to calculate such a value
     * is: minimum visible change = range of custom property value / corresponding pixel range. For
     * example, if the property to be animated is a progress (from 0 to 100) that corresponds to a
     * 200-pixel change. Then the min visible change should be 100 / 200. (i.e. 0.5).
     *
     * <p>It's not necessary to call this method when animating {@link ViewProperty}s, as the
     * minimum visible change will be derived from the property. For example, if the property to be
     * animated is in pixels (i.e. {@link #TRANSLATION_X}, {@link #TRANSLATION_Y},
     * {@link #TRANSLATION_Z}, @{@link #SCROLL_X} or {@link #SCROLL_Y}), the default minimum visible
     * change is 1 (pixel). For {@link #ROTATION}, {@link #ROTATION_X} or {@link #ROTATION_Y}, the
     * animation will use {@link #MIN_VISIBLE_CHANGE_ROTATION_DEGREES} as the min visible change,
     * which is 1/10. Similarly, the minimum visible change for alpha (
     * i.e. {@link #MIN_VISIBLE_CHANGE_ALPHA} is defined as 1 / 256.
     *
     * @param minimumVisibleChange minimum change in property value that is visible to users
     * @return the animation whose min visible change is being set
     * @throws IllegalArgumentException if the given threshold is not positive
     */
    public T setMinimumVisibleChange(@FloatRange(from = 0.0, fromInclusive = false)
            float minimumVisibleChange) {
        if (minimumVisibleChange <= 0) {
            throw new IllegalArgumentException("Minimum visible change must be positive.");
        }
        mMinVisibleChange = minimumVisibleChange;
        setValueThreshold(minimumVisibleChange * THRESHOLD_MULTIPLIER);
        return (T) this;
    }

    /**
     * Returns the minimum change in the animation property that could be visibly different to
     * users.
     *
     * @return minimum change in property value that is visible to users
     */
    public float getMinimumVisibleChange() {
        return mMinVisibleChange;
    }

    /**
     * Remove {@code null} entries from the list.
     */
    private static <T> void removeNullEntries(ArrayList<T> list) {
        // Clean up null entries
        for (int i = list.size() - 1; i >= 0; i--) {
            if (list.get(i) == null) {
                list.remove(i);
            }
        }
    }

    /**
     * Remove an entry from the list by marking it {@code null} and clean up later.
     */
    private static <T> void removeEntry(ArrayList<T> list, T entry) {
        int id = list.indexOf(entry);
        if (id >= 0) {
            list.set(id, null);
        }
    }

    /****************Animation Lifecycle Management***************/

    /**
     * Starts an animation. If the animation has already been started, no op. Note that calling
     * {@link #start()} will not immediately set the property value to start value of the animation.
     * The property values will be changed at each animation pulse, which happens before the draw
     * pass. As a result, the changes will be reflected in the next frame, the same as if the values
     * were set immediately. This method should only be called on main thread.
     *
     * @throws AndroidRuntimeException if this method is not called on the main thread
     */
    public void start() {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new AndroidRuntimeException("Animations may only be started on the main thread");
        }
        if (!mRunning) {
            startAnimationInternal();
        }
    }

    /**
     * Cancels the on-going animation. If the animation hasn't started, no op. Note that this method
     * should only be called on main thread.
     *
     * @throws AndroidRuntimeException if this method is not called on the main thread
     */
    public void cancel() {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new AndroidRuntimeException("Animations may only be canceled on the main thread");
        }
        if (mRunning) {
            endAnimationInternal(true);
        }
    }

    /**
     * Returns whether the animation is currently running.
     *
     * @return {@code true} if the animation is currently running, {@code false} otherwise
     */
    public boolean isRunning() {
        return mRunning;
    }

    /************************** Private APIs below ********************************/

    // This gets called when the animation is started, to finish the setup of the animation
    // before the animation pulsing starts.
    private void startAnimationInternal() {
        if (!mRunning) {
            mRunning = true;
            if (!mStartValueIsSet) {
                mValue = getPropertyValue();
            }
            // Sanity check:
            if (mValue > mMaxValue || mValue < mMinValue) {
                throw new IllegalArgumentException("Starting value need to be in between min"
                        + " value and max value");
            }
            AnimationHandler.getInstance().addAnimationFrameCallback(this, 0);
        }
    }

    /**
     * This gets call on each frame of the animation. Animation value and velocity are updated
     * in this method based on the new frame time. The property value of the view being animated
     * is then updated. The animation's ending conditions are also checked in this method. Once
     * the animation reaches equilibrium, the animation will come to its end, and end listeners
     * will be notified, if any.
     *
     * @hide
     */
    @Override
    public boolean doAnimationFrame(long frameTime) {
        if (mLastFrameTime == 0) {
            // First frame.
            mLastFrameTime = frameTime;
            setPropertyValue(mValue);
            return false;
        }
        long deltaT = frameTime - mLastFrameTime;
        mLastFrameTime = frameTime;
        boolean finished = updateValueAndVelocity(deltaT);
        // Clamp value & velocity.
        mValue = Math.min(mValue, mMaxValue);
        mValue = Math.max(mValue, mMinValue);

        setPropertyValue(mValue);

        if (finished) {
            endAnimationInternal(false);
        }
        return finished;
    }

    /**
     * Updates the animation state (i.e. value and velocity). This method is package private, so
     * subclasses can override this method to calculate the new value and velocity in their custom
     * way.
     *
     * @param deltaT time elapsed in millisecond since last frame
     * @return whether the animation has finished
     */
    abstract boolean updateValueAndVelocity(long deltaT);

    /**
     * Internal method to reset the animation states when animation is finished/canceled.
     */
    private void endAnimationInternal(boolean canceled) {
        mRunning = false;
        AnimationHandler.getInstance().removeCallback(this);
        mLastFrameTime = 0;
        mStartValueIsSet = false;
        for (int i = 0; i < mEndListeners.size(); i++) {
            if (mEndListeners.get(i) != null) {
                mEndListeners.get(i).onAnimationEnd(this, canceled, mValue, mVelocity);
            }
        }
        removeNullEntries(mEndListeners);
    }

    /**
     * Updates the property value through the corresponding setter.
     */
    void setPropertyValue(float value) {
        mProperty.setValue(mTarget, value);
        for (int i = 0; i < mUpdateListeners.size(); i++) {
            if (mUpdateListeners.get(i) != null) {
                mUpdateListeners.get(i).onAnimationUpdate(this, mValue, mVelocity);
            }
        }
        removeNullEntries(mUpdateListeners);
    }

    /**
     * Returns the default threshold.
     */
    float getValueThreshold() {
        return mMinVisibleChange * THRESHOLD_MULTIPLIER;
    }

    /**
     * Obtain the property value through the corresponding getter.
     */
    private float getPropertyValue() {
        return mProperty.getValue(mTarget);
    }

    /****************Sub class animations**************/
    /**
     * Returns the acceleration at the given value with the given velocity.
     **/
    abstract float getAcceleration(float value, float velocity);

    /**
     * Returns whether the animation has reached equilibrium.
     */
    abstract boolean isAtEquilibrium(float value, float velocity);

    /**
     * Updates the default value threshold for the animation based on the property to be animated.
     */
    abstract void setValueThreshold(float threshold);

    /**
     * An animation listener that receives end notifications from an animation.
     */
    public interface OnAnimationEndListener {
        /**
         * Notifies the end of an animation. Note that this callback will be invoked not only when
         * an animation reach equilibrium, but also when the animation is canceled.
         *
         * @param animation animation that has ended or was canceled
         * @param canceled whether the animation has been canceled
         * @param value the final value when the animation stopped
         * @param velocity the final velocity when the animation stopped
         */
        void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
                              float velocity);
    }

    /**
     * Implementors of this interface can add themselves as update listeners
     * to an <code>DynamicAnimation</code> instance to receive callbacks on every animation
     * frame, after the current frame's values have been calculated for that
     * <code>DynamicAnimation</code>.
     */
    public interface OnAnimationUpdateListener {

        /**
         * Notifies the occurrence of another frame of the animation.
         *
         * @param animation animation that the update listener is added to
         * @param value the current value of the animation
         * @param velocity the current velocity of the animation
         */
        void onAnimationUpdate(DynamicAnimation animation, float value, float velocity);
    }
}
