/*
 * Copyright (C) 2014 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 "AnimationContext.h"

#include "Animator.h"
#include "RenderNode.h"
#include "renderthread/TimeLord.h"

namespace android {
namespace uirenderer {

AnimationContext::AnimationContext(renderthread::TimeLord& clock)
        : mClock(clock)
        , mCurrentFrameAnimations(*this)
        , mNextFrameAnimations(*this)
        , mFrameTimeMs(0) {}

AnimationContext::~AnimationContext() {}

void AnimationContext::destroy() {
    startFrame(TreeInfo::MODE_RT_ONLY);
    while (mCurrentFrameAnimations.mNextHandle) {
        AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
        AnimatorManager& animators = current->mRenderNode->animators();
        animators.endAllActiveAnimators();
        LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
                            "endAllAnimators failed to remove from current frame list!");
    }
}

void AnimationContext::addAnimatingRenderNode(RenderNode& node) {
    if (!node.animators().hasAnimationHandle()) {
        AnimationHandle* handle = new AnimationHandle(node, *this);
        addAnimationHandle(handle);
    }
}

void AnimationContext::addAnimationHandle(AnimationHandle* handle) {
    handle->insertAfter(&mNextFrameAnimations);
}

void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
    LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
                        "Missed running animations last frame!");
    AnimationHandle* head = mNextFrameAnimations.mNextHandle;
    if (head) {
        mNextFrameAnimations.mNextHandle = nullptr;
        mCurrentFrameAnimations.mNextHandle = head;
        head->mPreviousHandle = &mCurrentFrameAnimations;
    }
    mFrameTimeMs = ns2ms(mClock.latestVsync());
}

void AnimationContext::runRemainingAnimations(TreeInfo& info) {
    while (mCurrentFrameAnimations.mNextHandle) {
        AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
        AnimatorManager& animators = current->mRenderNode->animators();
        animators.pushStaging();
        animators.animateNoDamage(info);
        LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
                            "Animate failed to remove from current frame list!");
    }
}

void AnimationContext::callOnFinished(BaseRenderNodeAnimator* animator,
                                      AnimationListener* listener) {
    listener->onAnimationFinished(animator);
}

AnimationHandle::AnimationHandle(AnimationContext& context)
        : mContext(context), mPreviousHandle(nullptr), mNextHandle(nullptr) {}

AnimationHandle::AnimationHandle(RenderNode& animatingNode, AnimationContext& context)
        : mRenderNode(&animatingNode)
        , mContext(context)
        , mPreviousHandle(nullptr)
        , mNextHandle(nullptr) {
    mRenderNode->animators().setAnimationHandle(this);
}

AnimationHandle::~AnimationHandle() {
    LOG_ALWAYS_FATAL_IF(mPreviousHandle || mNextHandle,
                        "AnimationHandle destroyed while still animating!");
}

void AnimationHandle::notifyAnimationsRan() {
    removeFromList();
    if (mRenderNode->animators().hasAnimators()) {
        mContext.addAnimationHandle(this);
    } else {
        release();
    }
}

void AnimationHandle::release() {
    LOG_ALWAYS_FATAL_IF(mRenderNode->animators().hasAnimators(),
                        "Releasing the handle for an RenderNode with outstanding animators!");
    removeFromList();
    mRenderNode->animators().setAnimationHandle(nullptr);
    delete this;
}

void AnimationHandle::insertAfter(AnimationHandle* prev) {
    removeFromList();
    mNextHandle = prev->mNextHandle;
    if (mNextHandle) {
        mNextHandle->mPreviousHandle = this;
    }
    prev->mNextHandle = this;
    mPreviousHandle = prev;
}

void AnimationHandle::removeFromList() {
    if (mPreviousHandle) {
        mPreviousHandle->mNextHandle = mNextHandle;
    }
    if (mNextHandle) {
        mNextHandle->mPreviousHandle = mPreviousHandle;
    }
    mPreviousHandle = nullptr;
    mNextHandle = nullptr;
}

} /* namespace uirenderer */
} /* namespace android */
