/*
 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution. 
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "CSSAnimationController.h"

#include "AnimationBase.h"
#include "AnimationEvent.h"
#include "CSSAnimationControllerPrivate.h"
#include "CSSPropertyAnimation.h"
#include "CSSPropertyParser.h"
#include "CompositeAnimation.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameView.h"
#include "Logging.h"
#include "PseudoElement.h"
#include "RenderView.h"
#include "TransitionEvent.h"
#include "WebKitAnimationEvent.h"
#include "WebKitTransitionEvent.h"

namespace WebCore {

// Allow a little more than 60fps to make sure we can at least hit that frame rate.
static const Seconds animationTimerDelay { 15_ms };
// Allow a little more than 30fps to make sure we can at least hit that frame rate.
static const Seconds animationTimerThrottledDelay { 30_ms };

class AnimationPrivateUpdateBlock {
public:
    AnimationPrivateUpdateBlock(CSSAnimationControllerPrivate& animationController)
        : m_animationController(animationController)
    {
        m_animationController.beginAnimationUpdate();
    }
    
    ~AnimationPrivateUpdateBlock()
    {
        m_animationController.endAnimationUpdate();
    }
    
    CSSAnimationControllerPrivate& m_animationController;
};

CSSAnimationControllerPrivate::CSSAnimationControllerPrivate(Frame& frame)
    : m_animationTimer(*this, &CSSAnimationControllerPrivate::animationTimerFired)
    , m_updateStyleIfNeededDispatcher(*this, &CSSAnimationControllerPrivate::updateStyleIfNeededDispatcherFired)
    , m_frame(frame)
    , m_beginAnimationUpdateCount(0)
    , m_waitingForAsyncStartNotification(false)
    , m_allowsNewAnimationsWhileSuspended(false)
{
}

CSSAnimationControllerPrivate::~CSSAnimationControllerPrivate() = default;

CompositeAnimation& CSSAnimationControllerPrivate::ensureCompositeAnimation(Element& element)
{
    element.setHasCSSAnimation();

    auto result = m_compositeAnimations.ensure(&element, [&] {
        return CompositeAnimation::create(*this);
    });

    if (animationsAreSuspendedForDocument(&element.document()))
        result.iterator->value->suspendAnimations();

    return *result.iterator->value;
}

bool CSSAnimationControllerPrivate::clear(Element& element)
{
    ASSERT(element.hasCSSAnimation() == m_compositeAnimations.contains(&element));

    if (!element.hasCSSAnimation())
        return false;
    element.clearHasCSSAnimation();

    auto it = m_compositeAnimations.find(&element);
    if (it == m_compositeAnimations.end())
        return false;

    LOG(Animations, "CSSAnimationControllerPrivate %p clear: %p", this, &element);

    m_eventsToDispatch.removeAllMatching([&] (const EventToDispatch& info) {
        return info.element.ptr() == &element;
    });

    m_elementChangesToDispatch.removeAllMatching([&](auto& currentElement) {
        return currentElement.ptr() == &element;
    });
    
    // Return false if we didn't do anything OR we are suspended (so we don't try to
    // do a invalidateStyleForSubtree() when suspended).
    // FIXME: The code below does the opposite of what the comment above says regarding suspended state.
    auto& animation = *it->value;
    bool result = animation.isSuspended();
    animation.clearElement();

    m_compositeAnimations.remove(it);

    return result;
}

std::optional<Seconds> CSSAnimationControllerPrivate::updateAnimations(SetChanged callSetChanged/* = DoNotCallSetChanged*/)
{
    AnimationPrivateUpdateBlock updateBlock(*this);
    std::optional<Seconds> timeToNextService;
    bool calledSetChanged = false;

    for (auto& compositeAnimation : m_compositeAnimations) {
        CompositeAnimation& animation = *compositeAnimation.value;
        if (!animation.isSuspended() && animation.hasAnimations()) {
            std::optional<Seconds> t = animation.timeToNextService();
            if (t && (!timeToNextService || t.value() < timeToNextService.value()))
                timeToNextService = t.value();
            if (timeToNextService && timeToNextService.value() == 0_s) {
                if (callSetChanged != CallSetChanged)
                    break;
                Element& element = *compositeAnimation.key;
                ASSERT(element.document().pageCacheState() == Document::NotInPageCache);
                element.invalidateStyleAndLayerComposition();
                calledSetChanged = true;
            }
        }
    }

    if (calledSetChanged)
        m_frame.document()->updateStyleIfNeeded();

    return timeToNextService;
}

void CSSAnimationControllerPrivate::updateAnimationTimerForElement(Element& element)
{
    std::optional<Seconds> timeToNextService;

    const CompositeAnimation* compositeAnimation = m_compositeAnimations.get(&element);
    if (!compositeAnimation->isSuspended() && compositeAnimation->hasAnimations())
        timeToNextService = compositeAnimation->timeToNextService();

    if (!timeToNextService)
        return;

    if (m_animationTimer.isActive() && (m_animationTimer.repeatInterval() || m_animationTimer.nextFireInterval() <= timeToNextService.value()))
        return;

    m_animationTimer.startOneShot(timeToNextService.value());
}

void CSSAnimationControllerPrivate::updateAnimationTimer(SetChanged callSetChanged/* = DoNotCallSetChanged*/)
{
    std::optional<Seconds> timeToNextService = updateAnimations(callSetChanged);

    LOG(Animations, "updateAnimationTimer: timeToNextService is %.2f", timeToNextService.value_or(Seconds { -1 }).value());

    // If we don't need service, we want to make sure the timer is no longer running
    if (!timeToNextService) {
        if (m_animationTimer.isActive())
            m_animationTimer.stop();
        return;
    }

    // If we want service immediately, we start a repeating timer to reduce the overhead of starting
    if (!timeToNextService.value()) {
        auto* page = m_frame.page();
        bool shouldThrottle = page && page->isLowPowerModeEnabled();
        Seconds delay = shouldThrottle ? animationTimerThrottledDelay : animationTimerDelay;

        if (!m_animationTimer.isActive() || m_animationTimer.repeatInterval() != delay)
            m_animationTimer.startRepeating(delay);
        return;
    }

    // Otherwise, we want to start a one-shot timer so we get here again
    m_animationTimer.startOneShot(timeToNextService.value());
}

void CSSAnimationControllerPrivate::updateStyleIfNeededDispatcherFired()
{
    fireEventsAndUpdateStyle();
}

void CSSAnimationControllerPrivate::fireEventsAndUpdateStyle()
{
    // Protect the frame from getting destroyed in the event handler
    Ref<Frame> protector(m_frame);

    bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_elementChangesToDispatch.isEmpty();

    // fire all the events
    Vector<EventToDispatch> eventsToDispatch = WTFMove(m_eventsToDispatch);
    for (auto& event : eventsToDispatch) {
        Element& element = event.element;
        if (event.eventType == eventNames().transitionendEvent)
            element.dispatchEvent(TransitionEvent::create(event.eventType, event.name, event.elapsedTime, PseudoElement::pseudoElementNameForEvents(element.pseudoId())));
        else
            element.dispatchEvent(AnimationEvent::create(event.eventType, event.name, event.elapsedTime));
    }

    for (auto& change : m_elementChangesToDispatch)
        change->invalidateStyleAndLayerComposition();

    m_elementChangesToDispatch.clear();

    if (updateStyle)
        m_frame.document()->updateStyleIfNeeded();
}

void CSSAnimationControllerPrivate::startUpdateStyleIfNeededDispatcher()
{
    if (!m_updateStyleIfNeededDispatcher.isActive())
        m_updateStyleIfNeededDispatcher.startOneShot(0_s);
}

void CSSAnimationControllerPrivate::addEventToDispatch(Element& element, const AtomicString& eventType, const String& name, double elapsedTime)
{
    m_eventsToDispatch.append({ element, eventType, name, elapsedTime });
    startUpdateStyleIfNeededDispatcher();
}

void CSSAnimationControllerPrivate::addElementChangeToDispatch(Element& element)
{
    m_elementChangesToDispatch.append(element);
    ASSERT(m_elementChangesToDispatch.last()->document().pageCacheState() == Document::NotInPageCache);
    startUpdateStyleIfNeededDispatcher();
}

void CSSAnimationControllerPrivate::animationFrameCallbackFired()
{
    std::optional<Seconds> timeToNextService = updateAnimations(CallSetChanged);

    if (timeToNextService)
        m_frame.document()->view()->scheduleAnimation();
}

void CSSAnimationControllerPrivate::animationTimerFired()
{
    // We need to keep the frame alive, since it owns us.
    Ref<Frame> protector(m_frame);

    // The animation timer might fire before the layout timer, in
    // which case we might create some animations with incorrect
    // values if we don't layout first.
    if (m_requiresLayout) {
        if (auto* frameView = m_frame.document()->view()) {
            if (frameView->needsLayout())
                frameView->forceLayout();
        }
        m_requiresLayout = false;
    }

    // Make sure animationUpdateTime is updated, so that it is current even if no
    // styleChange has happened (e.g. accelerated animations)
    AnimationPrivateUpdateBlock updateBlock(*this);

    // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
    // updateStyleIfNeeded. It will then call back to us with new information.
    updateAnimationTimer(CallSetChanged);

    // Fire events right away, to avoid a flash of unanimated style after an animation completes, and before
    // the 'end' event fires.
    fireEventsAndUpdateStyle();
}

bool CSSAnimationControllerPrivate::isRunningAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
{
    if (!renderer.element())
        return false;
    auto* animation = m_compositeAnimations.get(renderer.element());
    if (!animation)
        return false;
    return animation->isAnimatingProperty(property, false, runningState);
}

bool CSSAnimationControllerPrivate::isRunningAcceleratedAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
{
    if (!renderer.element())
        return false;
    auto* animation = m_compositeAnimations.get(renderer.element());
    if (!animation)
        return false;
    return animation->isAnimatingProperty(property, true, runningState);
}

void CSSAnimationControllerPrivate::updateThrottlingState()
{
    updateAnimationTimer();

    for (auto* childFrame = m_frame.tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling())
        childFrame->animation().updateThrottlingState();
}

Seconds CSSAnimationControllerPrivate::animationInterval() const
{
    if (!m_animationTimer.isActive())
        return Seconds { INFINITY };

    return Seconds { m_animationTimer.repeatInterval() };
}

void CSSAnimationControllerPrivate::suspendAnimations()
{
    if (isSuspended())
        return;

    suspendAnimationsForDocument(m_frame.document());

    // Traverse subframes
    for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
        child->animation().suspendAnimations();

    m_isSuspended = true;
}

void CSSAnimationControllerPrivate::resumeAnimations()
{
    if (!isSuspended())
        return;

    resumeAnimationsForDocument(m_frame.document());

    // Traverse subframes
    for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
        child->animation().resumeAnimations();

    m_isSuspended = false;
}

bool CSSAnimationControllerPrivate::animationsAreSuspendedForDocument(Document* document)
{
    return isSuspended() || m_suspendedDocuments.contains(document);
}

void CSSAnimationControllerPrivate::detachFromDocument(Document* document)
{
    m_suspendedDocuments.remove(document);
}

void CSSAnimationControllerPrivate::suspendAnimationsForDocument(Document* document)
{
    if (animationsAreSuspendedForDocument(document))
        return;

    m_suspendedDocuments.add(document);

    AnimationPrivateUpdateBlock updateBlock(*this);

    for (auto& animation : m_compositeAnimations) {
        if (&animation.key->document() == document)
            animation.value->suspendAnimations();
    }

    updateAnimationTimer();
}

void CSSAnimationControllerPrivate::resumeAnimationsForDocument(Document* document)
{
    if (!animationsAreSuspendedForDocument(document))
        return;

    detachFromDocument(document);

    AnimationPrivateUpdateBlock updateBlock(*this);

    for (auto& animation : m_compositeAnimations) {
        if (&animation.key->document() == document)
            animation.value->resumeAnimations();
    }

    updateAnimationTimer();
}

void CSSAnimationControllerPrivate::startAnimationsIfNotSuspended(Document* document)
{
    if (!animationsAreSuspendedForDocument(document) || allowsNewAnimationsWhileSuspended())
        resumeAnimationsForDocument(document);
}

void CSSAnimationControllerPrivate::setAllowsNewAnimationsWhileSuspended(bool allowed)
{
    m_allowsNewAnimationsWhileSuspended = allowed;
}

bool CSSAnimationControllerPrivate::pauseAnimationAtTime(Element& element, const AtomicString& name, double t)
{
    CompositeAnimation& compositeAnimation = ensureCompositeAnimation(element);
    if (compositeAnimation.pauseAnimationAtTime(name, t)) {
        element.invalidateStyleAndLayerComposition();
        startUpdateStyleIfNeededDispatcher();
        return true;
    }

    return false;
}

bool CSSAnimationControllerPrivate::pauseTransitionAtTime(Element& element, const String& property, double t)
{
    CompositeAnimation& compositeAnimation = ensureCompositeAnimation(element);
    if (compositeAnimation.pauseTransitionAtTime(cssPropertyID(property), t)) {
        element.invalidateStyleAndLayerComposition();
        startUpdateStyleIfNeededDispatcher();
        return true;
    }

    return false;
}

MonotonicTime CSSAnimationControllerPrivate::beginAnimationUpdateTime()
{
    ASSERT(m_beginAnimationUpdateCount);
    if (!m_beginAnimationUpdateTime)
        m_beginAnimationUpdateTime = MonotonicTime::now();

    return m_beginAnimationUpdateTime.value();
}

void CSSAnimationControllerPrivate::beginAnimationUpdate()
{
    if (!m_beginAnimationUpdateCount)
        m_beginAnimationUpdateTime = std::nullopt;
    ++m_beginAnimationUpdateCount;
}

void CSSAnimationControllerPrivate::endAnimationUpdate()
{
    ASSERT(m_beginAnimationUpdateCount > 0);
    if (m_beginAnimationUpdateCount == 1) {
        styleAvailable();
        if (!m_waitingForAsyncStartNotification)
            startTimeResponse(beginAnimationUpdateTime());
    }
    --m_beginAnimationUpdateCount;
}

void CSSAnimationControllerPrivate::receivedStartTimeResponse(MonotonicTime time)
{
    LOG(Animations, "CSSAnimationControllerPrivate %p receivedStartTimeResponse %f", this, time.secondsSinceEpoch().seconds());

    m_waitingForAsyncStartNotification = false;
    startTimeResponse(time);
}

std::unique_ptr<RenderStyle> CSSAnimationControllerPrivate::animatedStyleForElement(Element& element)
{
    auto* animation = m_compositeAnimations.get(&element);
    if (!animation)
        return nullptr;

    AnimationPrivateUpdateBlock animationUpdateBlock(*this);

    auto animatingStyle = animation->getAnimatedStyle();
    if (!animatingStyle)
        return nullptr;
    
    return animatingStyle;
}

bool CSSAnimationControllerPrivate::computeExtentOfAnimation(Element& element, LayoutRect& bounds) const
{
    auto* animation = m_compositeAnimations.get(&element);
    if (!animation)
        return true;

    if (!animation->isAnimatingProperty(CSSPropertyTransform, false, AnimationBase::Running | AnimationBase::Paused))
        return true;

    return animation->computeExtentOfTransformAnimation(bounds);
}

unsigned CSSAnimationControllerPrivate::numberOfActiveAnimations(Document* document) const
{
    unsigned count = 0;
    
    for (auto& animation : m_compositeAnimations) {
        if (&animation.key->document() == document)
            count += animation.value->numberOfActiveAnimations();
    }

    return count;
}

void CSSAnimationControllerPrivate::addToAnimationsWaitingForStyle(AnimationBase* animation)
{
    // Make sure this animation is not in the start time waiters
    m_animationsWaitingForStartTimeResponse.remove(animation);

    m_animationsWaitingForStyle.add(animation);
}

void CSSAnimationControllerPrivate::removeFromAnimationsWaitingForStyle(AnimationBase* animationToRemove)
{
    m_animationsWaitingForStyle.remove(animationToRemove);
}

void CSSAnimationControllerPrivate::styleAvailable()
{
    // Go through list of waiters and send them on their way
    for (const auto& waitingAnimation : m_animationsWaitingForStyle)
        waitingAnimation->styleAvailable();

    m_animationsWaitingForStyle.clear();
}

void CSSAnimationControllerPrivate::addToAnimationsWaitingForStartTimeResponse(AnimationBase* animation, bool willGetResponse)
{
    // If willGetResponse is true, it means this animation is actually waiting for a response
    // (which will come in as a call to notifyAnimationStarted()).
    // In that case we don't need to add it to this list. We just set a waitingForAResponse flag 
    // which says we are waiting for the response. If willGetResponse is false, this animation 
    // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for 
    // another animation to which it will sync.
    //
    // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is
    // true. If so, we just return and will do our work when the first notifyXXXStarted() call
    // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will
    // do our work right away. In both cases we call the onAnimationStartResponse() method
    // on each animation. In the first case we send in the time we got from notifyXXXStarted().
    // In the second case, we just pass in the beginAnimationUpdateTime().
    //
    // This will synchronize all software and accelerated animations started in the same 
    // updateStyleIfNeeded cycle.
    //
    
    if (willGetResponse)
        m_waitingForAsyncStartNotification = true;

    m_animationsWaitingForStartTimeResponse.add(animation);
}

void CSSAnimationControllerPrivate::removeFromAnimationsWaitingForStartTimeResponse(AnimationBase* animationToRemove)
{
    m_animationsWaitingForStartTimeResponse.remove(animationToRemove);
    
    if (m_animationsWaitingForStartTimeResponse.isEmpty())
        m_waitingForAsyncStartNotification = false;
}

void CSSAnimationControllerPrivate::startTimeResponse(MonotonicTime time)
{
    // Go through list of waiters and send them on their way

    for (const auto& animation : m_animationsWaitingForStartTimeResponse)
        animation->onAnimationStartResponse(time);
    
    m_animationsWaitingForStartTimeResponse.clear();
    m_waitingForAsyncStartNotification = false;
}

void CSSAnimationControllerPrivate::animationWillBeRemoved(AnimationBase* animation)
{
    LOG(Animations, "CSSAnimationControllerPrivate %p animationWillBeRemoved: %p", this, animation);

    removeFromAnimationsWaitingForStyle(animation);
    removeFromAnimationsWaitingForStartTimeResponse(animation);
#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
    removeFromAnimationsDependentOnScroll(animation);
#endif

    bool anyAnimationsWaitingForAsyncStart = false;
    for (auto& animation : m_animationsWaitingForStartTimeResponse) {
        if (animation->waitingForStartTime() && animation->isAccelerated()) {
            anyAnimationsWaitingForAsyncStart = true;
            break;
        }
    }

    if (!anyAnimationsWaitingForAsyncStart)
        m_waitingForAsyncStartNotification = false;
}

#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
void CSSAnimationControllerPrivate::addToAnimationsDependentOnScroll(AnimationBase* animation)
{
    m_animationsDependentOnScroll.add(animation);
}

void CSSAnimationControllerPrivate::removeFromAnimationsDependentOnScroll(AnimationBase* animation)
{
    m_animationsDependentOnScroll.remove(animation);
}

void CSSAnimationControllerPrivate::scrollWasUpdated()
{
    auto* view = m_frame.view();
    if (!view || !wantsScrollUpdates())
        return;

    m_scrollPosition = view->scrollPositionForFixedPosition().y().toFloat();

    // FIXME: This is updating all the animations, rather than just the ones
    // that are dependent on scroll. We to go from our AnimationBase to its CompositeAnimation
    // so we can execute code similar to updateAnimations.
    // https://bugs.webkit.org/show_bug.cgi?id=144170
    updateAnimations(CallSetChanged);
}
#endif

CSSAnimationController::CSSAnimationController(Frame& frame)
    : m_data(std::make_unique<CSSAnimationControllerPrivate>(frame))
{
}

CSSAnimationController::~CSSAnimationController() = default;

void CSSAnimationController::cancelAnimations(Element& element)
{
    if (!m_data->clear(element))
        return;

    if (element.document().renderTreeBeingDestroyed())
        return;
    ASSERT(element.document().pageCacheState() == Document::NotInPageCache);
    element.invalidateStyleAndLayerComposition();
}

AnimationUpdate CSSAnimationController::updateAnimations(Element& element, const RenderStyle& newStyle, const RenderStyle* oldStyle)
{
    bool hasOrHadAnimations = (oldStyle && oldStyle->hasAnimationsOrTransitions()) || newStyle.hasAnimationsOrTransitions();
    if (!hasOrHadAnimations)
        return { };

    if (element.document().pageCacheState() != Document::NotInPageCache)
        return { };

    // Don't run transitions when printing.
    if (element.document().renderView()->printing())
        return { };

    // Fetch our current set of implicit animations from a hashtable. We then compare them
    // against the animations in the style and make sure we're in sync. If destination values
    // have changed, we reset the animation. We then do a blend to get new values and we return
    // a new style.

    CompositeAnimation& compositeAnimation = m_data->ensureCompositeAnimation(element);
    auto update = compositeAnimation.animate(element, oldStyle, newStyle);

    auto* renderer = element.renderer();
    if ((renderer && renderer->parent()) || newStyle.animations() || (oldStyle && oldStyle->animations())) {
        auto& frameView = *element.document().view();
        if (compositeAnimation.hasAnimationThatDependsOnLayout())
            m_data->setRequiresLayout();
        m_data->updateAnimationTimerForElement(element);
        frameView.scheduleAnimation();
    }

    return update;
}

std::unique_ptr<RenderStyle> CSSAnimationController::animatedStyleForRenderer(RenderElement& renderer)
{
    std::unique_ptr<RenderStyle> result;

    if (renderer.style().hasAnimationsOrTransitions() && renderer.element())
        result = m_data->animatedStyleForElement(*renderer.element());

    if (!result)
        result = RenderStyle::clonePtr(renderer.style());

    return result;
}

bool CSSAnimationController::computeExtentOfAnimation(RenderElement& renderer, LayoutRect& bounds) const
{
    if (!renderer.element())
        return true;
    if (!renderer.style().hasAnimationsOrTransitions())
        return true;

    return m_data->computeExtentOfAnimation(*renderer.element(), bounds);
}

void CSSAnimationController::notifyAnimationStarted(RenderElement& renderer, MonotonicTime startTime)
{
    LOG(Animations, "CSSAnimationController %p notifyAnimationStarted on renderer %p, time=%f", this, &renderer, startTime.secondsSinceEpoch().seconds());
    UNUSED_PARAM(renderer);

    AnimationUpdateBlock animationUpdateBlock(this);
    m_data->receivedStartTimeResponse(startTime);
}

bool CSSAnimationController::pauseAnimationAtTime(Element& element, const AtomicString& name, double t)
{
    AnimationUpdateBlock animationUpdateBlock(this);
    return m_data->pauseAnimationAtTime(element, name, t);
}

unsigned CSSAnimationController::numberOfActiveAnimations(Document* document) const
{
    return m_data->numberOfActiveAnimations(document);
}

bool CSSAnimationController::pauseTransitionAtTime(Element& element, const String& property, double t)
{
    AnimationUpdateBlock animationUpdateBlock(this);
    return m_data->pauseTransitionAtTime(element, property, t);
}

bool CSSAnimationController::isRunningAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
{
    if (!renderer.style().hasAnimationsOrTransitions())
        return false;
    return m_data->isRunningAnimationOnRenderer(renderer, property, runningState);
}

bool CSSAnimationController::isRunningAcceleratedAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
{
    if (!renderer.style().hasAnimationsOrTransitions())
        return false;
    return m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property, runningState);
}

bool CSSAnimationController::isSuspended() const
{
    return m_data->isSuspended();
}

void CSSAnimationController::suspendAnimations()
{
    LOG(Animations, "controller is suspending animations");
    m_data->suspendAnimations();
}

void CSSAnimationController::resumeAnimations()
{
    LOG(Animations, "controller is resuming animations");
    m_data->resumeAnimations();
}

bool CSSAnimationController::allowsNewAnimationsWhileSuspended() const
{
    return m_data->allowsNewAnimationsWhileSuspended();
}

void CSSAnimationController::setAllowsNewAnimationsWhileSuspended(bool allowed)
{
    m_data->setAllowsNewAnimationsWhileSuspended(allowed);
}

void CSSAnimationController::serviceAnimations()
{
    m_data->animationFrameCallbackFired();
}

void CSSAnimationController::updateThrottlingState()
{
    m_data->updateThrottlingState();
}

Seconds CSSAnimationController::animationInterval() const
{
    return m_data->animationInterval();
}

bool CSSAnimationController::animationsAreSuspendedForDocument(Document* document)
{
    return m_data->animationsAreSuspendedForDocument(document);
}

void CSSAnimationController::detachFromDocument(Document* document)
{
    return m_data->detachFromDocument(document);
}

void CSSAnimationController::suspendAnimationsForDocument(Document* document)
{
    LOG(Animations, "suspending animations for document %p", document);
    m_data->suspendAnimationsForDocument(document);
}

void CSSAnimationController::resumeAnimationsForDocument(Document* document)
{
    LOG(Animations, "resuming animations for document %p", document);
    AnimationUpdateBlock animationUpdateBlock(this);
    m_data->resumeAnimationsForDocument(document);
}

void CSSAnimationController::startAnimationsIfNotSuspended(Document* document)
{
    LOG(Animations, "animations may start for document %p", document);

    AnimationUpdateBlock animationUpdateBlock(this);
    m_data->startAnimationsIfNotSuspended(document);
}

void CSSAnimationController::beginAnimationUpdate()
{
    m_data->beginAnimationUpdate();
}

void CSSAnimationController::endAnimationUpdate()
{
    m_data->endAnimationUpdate();
}

bool CSSAnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property)
{
    return CSSPropertyAnimation::animationOfPropertyIsAccelerated(property);
}

#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
bool CSSAnimationController::wantsScrollUpdates() const
{
    return m_data->wantsScrollUpdates();
}

void CSSAnimationController::scrollWasUpdated()
{
    m_data->scrollWasUpdated();
}
#endif

bool CSSAnimationController::hasAnimations() const
{
    return m_data->hasAnimations();
}

} // namespace WebCore
