/*
 * 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 "AnimatorManager.h"

#include <algorithm>

#include "AnimationContext.h"
#include "Animator.h"
#include "DamageAccumulator.h"
#include "RenderNode.h"

namespace android {
namespace uirenderer {

using namespace std;

static void detach(sp<BaseRenderNodeAnimator>& animator) {
    animator->detach();
}

AnimatorManager::AnimatorManager(RenderNode& parent) : mParent(parent), mAnimationHandle(nullptr) {}

AnimatorManager::~AnimatorManager() {
    for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
    for_each(mAnimators.begin(), mAnimators.end(), detach);
}

void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
    RenderNode* stagingTarget = animator->stagingTarget();
    if (stagingTarget == &mParent) {
        return;
    }
    mNewAnimators.emplace_back(animator.get());
    // If the animator is already attached to other RenderNode, remove it from that RenderNode's
    // new animator list. This ensures one animator only ends up in one newAnimatorList during one
    // frame, even when it's added multiple times to multiple targets.
    if (stagingTarget) {
        stagingTarget->removeAnimator(animator);
    }
    animator->attach(&mParent);
}

void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
    mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
                        mNewAnimators.end());
}

void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
    LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
    mAnimationHandle = handle;
    LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
                        "Lost animation handle on %p (%s) with outstanding animators!", &mParent,
                        mParent.getName());
}

void AnimatorManager::pushStaging() {
    if (mNewAnimators.size()) {
        if (CC_UNLIKELY(!mAnimationHandle)) {
            ALOGW("Trying to start new animators on %p (%s) without an animation handle!", &mParent,
                  mParent.getName());
            return;
        }

        // Only add new animators that are not already in the mAnimators list
        for (auto& anim : mNewAnimators) {
            if (anim->target() != &mParent) {
                mAnimators.push_back(std::move(anim));
            }
        }
        mNewAnimators.clear();
    }
    for (auto& animator : mAnimators) {
        animator->pushStaging(mAnimationHandle->context());
    }
}

void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
    LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
    mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
}

class AnimateFunctor {
public:
    AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
            : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}

    bool operator()(sp<BaseRenderNodeAnimator>& animator) {
        *mDirtyMask |= animator->dirtyMask();
        bool remove = animator->animate(mContext);
        if (remove) {
            animator->detach();
        } else {
            if (animator->isRunning()) {
                mInfo.out.hasAnimations = true;
            }
            if (CC_UNLIKELY(!animator->mayRunAsync())) {
                mInfo.out.requiresUiRedraw = true;
            }
        }
        return remove;
    }

private:
    TreeInfo& mInfo;
    AnimationContext& mContext;
    uint32_t* mDirtyMask;
};

uint32_t AnimatorManager::animate(TreeInfo& info) {
    if (!mAnimators.size()) return 0;

    // TODO: Can we target this better? For now treat it like any other staging
    // property push and just damage self before and after animators are run

    mParent.damageSelf(info);
    info.damageAccumulator->popTransform();

    uint32_t dirty = animateCommon(info);

    info.damageAccumulator->pushTransform(&mParent);
    mParent.damageSelf(info);

    return dirty;
}

void AnimatorManager::animateNoDamage(TreeInfo& info) {
    animateCommon(info);
}

uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
    uint32_t dirtyMask = 0;
    AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
    auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
    mAnimators.erase(newEnd, mAnimators.end());
    mAnimationHandle->notifyAnimationsRan();
    mParent.mProperties.updateMatrix();
    return dirtyMask;
}

static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
    animator->cancel();
    if (animator->listener()) {
        animator->listener()->onAnimationFinished(animator.get());
    }
}

void AnimatorManager::endAllStagingAnimators() {
    ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
    // This works because this state can only happen on the UI thread,
    // which means we're already on the right thread to invoke listeners
    for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
    mNewAnimators.clear();
}

class EndActiveAnimatorsFunctor {
public:
    explicit EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}

    void operator()(sp<BaseRenderNodeAnimator>& animator) { animator->forceEndNow(mContext); }

private:
    AnimationContext& mContext;
};

void AnimatorManager::endAllActiveAnimators() {
    ALOGD("endAllActiveAnimators on %p (%s) with handle %p", &mParent, mParent.getName(),
          mAnimationHandle);
    EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
    for_each(mAnimators.begin(), mAnimators.end(), functor);
    mAnimators.clear();
    mAnimationHandle->release();
}

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