/*
 * Copyright (C) 2016 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.
 */

#include "PropertyValuesAnimatorSet.h"
#include "RenderNode.h"

#include <algorithm>

namespace android {
namespace uirenderer {

void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
                                                    Interpolator* interpolator, nsecs_t startDelay,
                                                    nsecs_t duration, int repeatCount,
                                                    RepeatMode repeatMode) {
    PropertyAnimator* animator = new PropertyAnimator(
            propertyValuesHolder, interpolator, startDelay, duration, repeatCount, repeatMode);
    mAnimators.emplace_back(animator);

    // Check whether any child animator is infinite after adding it them to the set.
    if (repeatCount == -1) {
        mIsInfinite = true;
    }
}

PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() : BaseRenderNodeAnimator(1.0f) {
    setStartValue(0);
    mLastFraction = 0.0f;
    setInterpolator(new LinearInterpolator());
    setListener(new PropertyAnimatorSetListener(this));
}

void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) {
    if (mOneShotListener.get()) {
        sp<AnimationListener> listener = std::move(mOneShotListener);
        // Set the listener to nullptr before the onAnimationFinished callback, rather than after,
        // for two reasons:
        // 1) We need to prevent changes to mOneShotListener during the onAnimationFinished
        // callback (specifically in AnimationListenerBridge::onAnimationFinished(...) from
        // triggering dtor of the bridge and potentially unsafely re-entering
        // AnimationListenerBridge::onAnimationFinished(...).
        // 2) It's possible that there are changes to the listener during the callback, therefore
        // we need to reset the listener before the callback rather than afterwards.
        mOneShotListener = nullptr;
        listener->onAnimationFinished(animator);
    }
}

float PropertyValuesAnimatorSet::getValue(RenderNode* target) const {
    return mLastFraction;
}

void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) {
    mLastFraction = value;
}

void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
    if (playTime == 0 && mDuration > 0) {
        // Reset all the animators
        for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) {
            // Note that this set may containing animators modifying the same property, so when we
            // reset the animators, we need to make sure the animators that end the first will
            // have the final say on what the property value should be.
            (*it)->setFraction(0, 0);
        }
    } else {
        for (auto& anim : mAnimators) {
            anim->setCurrentPlayTime(playTime);
        }
    }
}

void PropertyValuesAnimatorSet::start(AnimationListener* listener) {
    init();
    mOneShotListener = listener;
    mRequestId++;
    BaseRenderNodeAnimator::start();
}

void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) {
    init();
    mOneShotListener = listener;
    mRequestId++;
    BaseRenderNodeAnimator::reverse();
}

void PropertyValuesAnimatorSet::reset() {
    mRequestId++;
    BaseRenderNodeAnimator::reset();
}

void PropertyValuesAnimatorSet::end() {
    mRequestId++;
    BaseRenderNodeAnimator::end();
}

void PropertyValuesAnimatorSet::init() {
    if (mInitialized) {
        return;
    }

    // Sort the animators by their total duration. Note that all the animators in the set start at
    // the same time, so the ones with longer total duration (which includes start delay) will
    // be the ones that end later.
    std::sort(mAnimators.begin(), mAnimators.end(),
              [](auto& a, auto& b) { return a->getTotalDuration() < b->getTotalDuration(); });
    mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration();
    mInitialized = true;
}

uint32_t PropertyValuesAnimatorSet::dirtyMask() {
    return RenderNode::DISPLAY_LIST;
}

PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator,
                                   nsecs_t startDelay, nsecs_t duration, int repeatCount,
                                   RepeatMode repeatMode)
        : mPropertyValuesHolder(holder)
        , mInterpolator(interpolator)
        , mStartDelay(startDelay)
        , mDuration(duration) {
    if (repeatCount < 0) {
        mRepeatCount = UINT32_MAX;
    } else {
        mRepeatCount = repeatCount;
    }
    mRepeatMode = repeatMode;
    mTotalDuration = ((nsecs_t)mRepeatCount + 1) * mDuration + mStartDelay;
}

void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
    if (playTime < mStartDelay) {
        return;
    }

    float currentIterationFraction;
    long iteration;
    if (playTime >= mTotalDuration) {
        // Reached the end of the animation.
        iteration = mRepeatCount;
        currentIterationFraction = 1.0f;
    } else {
        // play time here is in range [mStartDelay, mTotalDuration)
        iteration = (playTime - mStartDelay) / mDuration;
        currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float)mDuration;
    }
    setFraction(currentIterationFraction, iteration);
}

void PropertyAnimator::setFraction(float fraction, long iteration) {
    double totalFraction = fraction + iteration;
    // This makes sure we only set the fraction = repeatCount + 1 once. It is needed because there
    // might be another animator modifying the same property after this animator finishes, we need
    // to make sure we don't set conflicting values on the same property within one frame.
    if ((mLatestFraction == mRepeatCount + 1.0) && (totalFraction >= mRepeatCount + 1.0)) {
        return;
    }

    mLatestFraction = totalFraction;
    // Check the play direction (i.e. reverse or restart) every other iteration, and calculate the
    // fraction based on the play direction.
    if (iteration % 2 && mRepeatMode == RepeatMode::Reverse) {
        fraction = 1.0f - fraction;
    }
    float interpolatedFraction = mInterpolator->interpolate(fraction);
    mPropertyValuesHolder->setFraction(interpolatedFraction);
}

void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) {
    mSet->onFinished(animator);
}
}
}
