/*
 * 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 = mClock.computeFrameTimeMs();
}

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 */
