/*
 * 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 "TreeInfo.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();
    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() {
    LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
            "Missed running animations last frame!");
    AnimationHandle* head = mNextFrameAnimations.mNextHandle;
    if (head) {
        mNextFrameAnimations.mNextHandle = NULL;
        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(NULL)
        , mNextHandle(NULL) {
}

AnimationHandle::AnimationHandle(RenderNode& animatingNode, AnimationContext& context)
        : mRenderNode(&animatingNode)
        , mContext(context)
        , mPreviousHandle(NULL)
        , mNextHandle(NULL) {
    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(NULL);
    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 = NULL;
    mNextHandle = NULL;
}

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