/*
 * 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();
        if (info.mode == TreeInfo::MODE_FULL) {
            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 */
