/*
 * 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), mCancelAllAnimators(false) {}

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();
    }

    if (mCancelAllAnimators) {
        for (auto& animator : mAnimators) {
            animator->forceEndNow(mAnimationHandle->context());
        }
        mCancelAllAnimators = false;
    } else {
        // create a copy of mAnimators as onAnimatorTargetChanged can erase mAnimators.
        FatVector<sp<BaseRenderNodeAnimator>> animators;
        animators.reserve(mAnimators.size());
        for (const auto& animator : mAnimators) {
            animators.push_back(animator);
        }
        for (auto& animator : animators) {
            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();
}

void AnimatorManager::forceEndAnimators() {
    mCancelAllAnimators = true;
}

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