/*
 * 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);
}

}
}
