/*
 * Copyright (C) 2013 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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 "core/animation/Animation.h"

#include "core/animation/AnimationTimeline.h"
#include "core/animation/KeyframeEffect.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/events/AnimationPlayerEvent.h"
#include "core/frame/UseCounter.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/TraceEvent.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorAnimationPlayer.h"
#include "public/platform/WebCompositorSupport.h"
#include "wtf/MathExtras.h"

namespace blink {

namespace {

static unsigned nextSequenceNumber()
{
    static unsigned next = 0;
    return ++next;
}

}

Animation* Animation::create(AnimationEffect* effect, AnimationTimeline* timeline)
{
    if (!timeline) {
        // FIXME: Support creating animations without a timeline.
        return nullptr;
    }

    Animation* animation = new Animation(timeline->document()->contextDocument().get(), *timeline, effect);
    animation->suspendIfNeeded();

    if (timeline) {
        timeline->animationAttached(*animation);
        animation->attachCompositorTimeline();
    }

    return animation;
}

Animation::Animation(ExecutionContext* executionContext, AnimationTimeline& timeline, AnimationEffect* content)
    : ActiveDOMObject(executionContext)
    , m_playState(Idle)
    , m_playbackRate(1)
    , m_startTime(nullValue())
    , m_holdTime(0)
    , m_startClip(-std::numeric_limits<double>::infinity())
    , m_endClip(std::numeric_limits<double>::infinity())
    , m_sequenceNumber(nextSequenceNumber())
    , m_content(content)
    , m_timeline(&timeline)
    , m_paused(false)
    , m_held(true)
    , m_isPausedForTesting(false)
    , m_isCompositedAnimationDisabledForTesting(false)
    , m_outdated(false)
    , m_finished(true)
    , m_compositorState(nullptr)
    , m_compositorPending(false)
    , m_compositorGroup(0)
    , m_currentTimePending(false)
    , m_stateIsBeingUpdated(false)
{
    if (m_content) {
        if (m_content->animation()) {
            m_content->animation()->cancel();
            m_content->animation()->setEffect(0);
        }
        m_content->attach(this);
    }
    InspectorInstrumentation::didCreateAnimation(m_timeline->document(), m_sequenceNumber);
}

Animation::~Animation()
{
    destroyCompositorPlayer();
}

double Animation::effectEnd() const
{
    return m_content ? m_content->endTimeInternal() : 0;
}

bool Animation::limited(double currentTime) const
{
    return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && currentTime >= effectEnd());
}

void Animation::setCurrentTime(double newCurrentTime)
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    m_currentTimePending = false;
    setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand);

    if (calculatePlayState() == Finished)
        m_startTime = calculateStartTime(newCurrentTime);
}

void Animation::setCurrentTimeInternal(double newCurrentTime, TimingUpdateReason reason)
{
    ASSERT(std::isfinite(newCurrentTime));

    bool oldHeld = m_held;
    bool outdated = false;
    bool isLimited = limited(newCurrentTime);
    m_held = m_paused || !m_playbackRate || isLimited || std::isnan(m_startTime);
    if (m_held) {
        if (!oldHeld || m_holdTime != newCurrentTime)
            outdated = true;
        m_holdTime = newCurrentTime;
        if (m_paused || !m_playbackRate) {
            m_startTime = nullValue();
        } else if (isLimited && std::isnan(m_startTime) && reason == TimingUpdateForAnimationFrame) {
            m_startTime = calculateStartTime(newCurrentTime);
        }
    } else {
        m_holdTime = nullValue();
        m_startTime = calculateStartTime(newCurrentTime);
        m_finished = false;
        outdated = true;
    }

    if (outdated) {
        setOutdated();
    }
}

// Update timing to reflect updated animation clock due to tick
void Animation::updateCurrentTimingState(TimingUpdateReason reason)
{
    if (m_held) {
        double newCurrentTime = m_holdTime;
        if (playStateInternal() == Finished && !isNull(m_startTime) && m_timeline) {
            // Add hystersis due to floating point error accumulation
            if (!limited(calculateCurrentTime() + 0.001 * m_playbackRate)) {
                // The current time became unlimited, eg. due to a backwards
                // seek of the timeline.
                newCurrentTime = calculateCurrentTime();
            } else if (!limited(m_holdTime)) {
                // The hold time became unlimited, eg. due to the effect
                // becoming longer.
                newCurrentTime = clampTo<double>(calculateCurrentTime(), 0, effectEnd());
            }
        }
        setCurrentTimeInternal(newCurrentTime, reason);
    } else if (limited(calculateCurrentTime())) {
        m_held = true;
        m_holdTime = m_playbackRate < 0 ? 0 : effectEnd();
    }
}

double Animation::startTime(bool& isNull) const
{
    double result = startTime();
    isNull = std::isnan(result);
    return result;
}

double Animation::startTime() const
{
    return m_startTime * 1000;
}

double Animation::currentTime(bool& isNull)
{
    double result = currentTime();
    isNull = std::isnan(result);
    return result;
}

double Animation::currentTime()
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (m_currentTimePending || playStateInternal() == Idle)
        return std::numeric_limits<double>::quiet_NaN();

    return currentTimeInternal() * 1000;
}

double Animation::currentTimeInternal() const
{
    double result = m_held ? m_holdTime : calculateCurrentTime();
#if ENABLE(ASSERT)
    const_cast<Animation*>(this)->updateCurrentTimingState(TimingUpdateOnDemand);
    ASSERT(result == (m_held ? m_holdTime : calculateCurrentTime()));
#endif
    return result;
}

double Animation::unlimitedCurrentTimeInternal() const
{
#if ENABLE(ASSERT)
    currentTimeInternal();
#endif
    return playStateInternal() == Paused || isNull(m_startTime)
        ? currentTimeInternal()
        : calculateCurrentTime();
}

bool Animation::preCommit(int compositorGroup, bool startOnCompositor)
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);

    bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate);
    bool hardChange = m_compositorState && (m_compositorState->effectChanged || m_compositorState->startTime != m_startTime);

    // FIXME: softChange && !hardChange should generate a Pause/ThenStart,
    // not a Cancel, but we can't communicate these to the compositor yet.

    bool changed = softChange || hardChange;
    bool shouldCancel = (!playing() && m_compositorState) || changed;
    bool shouldStart = playing() && (!m_compositorState || changed);

    if (shouldCancel && shouldStart && m_compositorState && m_compositorState->pendingAction == Start) {
        // Restarting but still waiting for a start time.
        return false;
    }

    if (shouldCancel) {
        cancelAnimationOnCompositor();
        m_compositorState = nullptr;
    }

    ASSERT(!m_compositorState || !std::isnan(m_compositorState->startTime));

    if (!shouldStart) {
        m_currentTimePending = false;
    }

    if (shouldStart) {
        m_compositorGroup = compositorGroup;
        if (startOnCompositor) {
            if (isCandidateForAnimationOnCompositor())
                createCompositorPlayer();

            if (maybeStartAnimationOnCompositor())
                m_compositorState = adoptPtr(new CompositorState(*this));
            else
                cancelIncompatibleAnimationsOnCompositor();
        }
    }

    return true;
}

void Animation::postCommit(double timelineTime)
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);

    m_compositorPending = false;

    if (!m_compositorState || m_compositorState->pendingAction == None)
        return;

    switch (m_compositorState->pendingAction) {
    case Start:
        if (!std::isnan(m_compositorState->startTime)) {
            ASSERT(m_startTime == m_compositorState->startTime);
            m_compositorState->pendingAction = None;
        }
        break;
    case Pause:
    case PauseThenStart:
        ASSERT(std::isnan(m_startTime));
        m_compositorState->pendingAction = None;
        setCurrentTimeInternal((timelineTime - m_compositorState->startTime) * m_playbackRate, TimingUpdateForAnimationFrame);
        m_currentTimePending = false;
        break;
    default:
        ASSERT_NOT_REACHED();
    }
}

void Animation::notifyCompositorStartTime(double timelineTime)
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);

    if (m_compositorState) {
        ASSERT(m_compositorState->pendingAction == Start);
        ASSERT(std::isnan(m_compositorState->startTime));

        double initialCompositorHoldTime = m_compositorState->holdTime;
        m_compositorState->pendingAction = None;
        m_compositorState->startTime = timelineTime + currentTimeInternal() / -m_playbackRate;

        if (m_startTime == timelineTime) {
            // The start time was set to the incoming compositor start time.
            // Unlikely, but possible.
            // FIXME: Depending on what changed above this might still be pending.
            // Maybe...
            m_currentTimePending = false;
            return;
        }

        if (!std::isnan(m_startTime) || currentTimeInternal() != initialCompositorHoldTime) {
            // A new start time or current time was set while starting.
            setCompositorPending(true);
            return;
        }
    }

    notifyStartTime(timelineTime);
}

void Animation::notifyStartTime(double timelineTime)
{
    if (playing()) {
        ASSERT(std::isnan(m_startTime));
        ASSERT(m_held);

        if (m_playbackRate == 0) {
            setStartTimeInternal(timelineTime);
        } else {
            setStartTimeInternal(timelineTime + currentTimeInternal() / -m_playbackRate);
        }

        // FIXME: This avoids marking this animation as outdated needlessly when a start time
        // is notified, but we should refactor how outdating works to avoid this.
        clearOutdated();
        m_currentTimePending = false;
    }
}

bool Animation::affects(const Element& element, CSSPropertyID property) const
{
    if (!m_content || !m_content->isKeyframeEffect())
        return false;

    const KeyframeEffect* effect = toKeyframeEffect(m_content.get());
    return (effect->target() == &element) && effect->affects(PropertyHandle(property));
}

double Animation::calculateStartTime(double currentTime) const
{
    return m_timeline->effectiveTime() - currentTime / m_playbackRate;
}

double Animation::calculateCurrentTime() const
{
    if (isNull(m_startTime) || !m_timeline)
        return 0;
    return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate;
}

void Animation::setStartTime(double startTime)
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (m_paused || playStateInternal() == Idle)
        return;
    if (startTime == m_startTime)
        return;

    m_currentTimePending = false;
    setStartTimeInternal(startTime / 1000);
}

void Animation::setStartTimeInternal(double newStartTime)
{
    ASSERT(!m_paused);
    ASSERT(std::isfinite(newStartTime));
    ASSERT(newStartTime != m_startTime);

    bool hadStartTime = hasStartTime();
    double previousCurrentTime = currentTimeInternal();
    m_startTime = newStartTime;
    if (m_held && m_playbackRate) {
        // If held, the start time would still be derrived from the hold time.
        // Force a new, limited, current time.
        m_held = false;
        double currentTime = calculateCurrentTime();
        if (m_playbackRate > 0 && currentTime > effectEnd()) {
            currentTime = effectEnd();
        } else if (m_playbackRate < 0 && currentTime < 0) {
            currentTime = 0;
        }
        setCurrentTimeInternal(currentTime, TimingUpdateOnDemand);
    }
    updateCurrentTimingState(TimingUpdateOnDemand);
    double newCurrentTime = currentTimeInternal();

    if (previousCurrentTime != newCurrentTime) {
        setOutdated();
    } else if (!hadStartTime && m_timeline) {
        // Even though this animation is not outdated, time to effect change is
        // infinity until start time is set.
        m_timeline->wake();
    }
}

bool Animation::clipped(double time)
{
    ASSERT(!isNull(time));
    return time <= m_startClip || time > m_endClip + effectEnd();
}

void Animation::setEffect(AnimationEffect* newEffect)
{
    if (m_content == newEffect)
        return;
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, SetCompositorPendingWithEffectChanged);

    double storedCurrentTime = currentTimeInternal();
    if (m_content)
        m_content->detach();
    m_content = newEffect;
    if (newEffect) {
        // FIXME: This logic needs to be updated once groups are implemented
        if (newEffect->animation()) {
            newEffect->animation()->cancel();
            newEffect->animation()->setEffect(0);
        }
        newEffect->attach(this);
        setOutdated();
    }
    setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand);
}

const char* Animation::playStateString(AnimationPlayState playState)
{
    switch (playState) {
    case Idle:
        return "idle";
    case Pending:
        return "pending";
    case Running:
        return "running";
    case Paused:
        return "paused";
    case Finished:
        return "finished";
    default:
        ASSERT_NOT_REACHED();
        return "";
    }
}

Animation::AnimationPlayState Animation::playStateInternal() const
{
    return m_playState;
}

Animation::AnimationPlayState Animation::calculatePlayState()
{
    if (m_playState == Idle)
        return Idle;
    if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackRate != 0))
        return Pending;
    if (m_paused)
        return Paused;
    if (limited())
        return Finished;
    return Running;
}

void Animation::pause()
{
    if (m_paused)
        return;

    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (playing()) {
        m_currentTimePending = true;
    }
    m_paused = true;
    setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand);
}

void Animation::unpause()
{
    if (!m_paused)
        return;

    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    m_currentTimePending = true;
    unpauseInternal();
}

void Animation::unpauseInternal()
{
    if (!m_paused)
        return;
    m_paused = false;
    setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand);
}

void Animation::play()
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (!playing())
        m_startTime = nullValue();

    if (playStateInternal() == Idle) {
        // We may not go into the pending state, but setting it to something other
        // than Idle here will force an update.
        ASSERT(isNull(m_startTime));
        m_playState = Pending;
        m_held = true;
        m_holdTime = 0;
    }

    m_finished = false;
    unpauseInternal();
    if (!m_content)
        return;
    double currentTime = this->currentTimeInternal();
    if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= effectEnd())) {
        m_startTime = nullValue();
        setCurrentTimeInternal(0, TimingUpdateOnDemand);
    } else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > effectEnd())) {
        m_startTime = nullValue();
        setCurrentTimeInternal(effectEnd(), TimingUpdateOnDemand);
    }
}

void Animation::reverse()
{
    if (!m_playbackRate) {
        return;
    }

    setPlaybackRateInternal(-m_playbackRate);
    play();
}

void Animation::finish(ExceptionState& exceptionState)
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (!m_playbackRate || playStateInternal() == Idle) {
        return;
    }
    if (m_playbackRate > 0 && effectEnd() == std::numeric_limits<double>::infinity()) {
        exceptionState.throwDOMException(InvalidStateError, "Animation has effect whose end time is infinity.");
        return;
    }

    double newCurrentTime = m_playbackRate < 0 ? 0 : effectEnd();
    setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand);
    if (!paused()) {
        m_startTime = calculateStartTime(newCurrentTime);
    }

    m_currentTimePending = false;
    ASSERT(playStateInternal() != Idle);
    ASSERT(limited());
}

ScriptPromise Animation::finished(ScriptState* scriptState)
{
    if (!m_finishedPromise) {
        m_finishedPromise = new AnimationPromise(scriptState->executionContext(), this, AnimationPromise::Finished);
        if (playStateInternal() == Finished)
            m_finishedPromise->resolve(this);
    }
    return m_finishedPromise->promise(scriptState->world());
}

ScriptPromise Animation::ready(ScriptState* scriptState)
{
    if (!m_readyPromise) {
        m_readyPromise = new AnimationPromise(scriptState->executionContext(), this, AnimationPromise::Ready);
        if (playStateInternal() != Pending)
            m_readyPromise->resolve(this);
    }
    return m_readyPromise->promise(scriptState->world());
}

const AtomicString& Animation::interfaceName() const
{
    return EventTargetNames::AnimationPlayer;
}

ExecutionContext* Animation::executionContext() const
{
    return ActiveDOMObject::executionContext();
}

bool Animation::hasPendingActivity() const
{
    return m_pendingFinishedEvent || (!m_finished && hasEventListeners(EventTypeNames::finish));
}

void Animation::stop()
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    m_finished = true;
    m_pendingFinishedEvent = nullptr;
}

bool Animation::dispatchEventInternal(PassRefPtrWillBeRawPtr<Event> event)
{
    if (m_pendingFinishedEvent == event)
        m_pendingFinishedEvent = nullptr;
    return EventTargetWithInlineData::dispatchEventInternal(event);
}

double Animation::playbackRate() const
{
    return m_playbackRate;
}

void Animation::setPlaybackRate(double playbackRate)
{
    if (playbackRate == m_playbackRate)
        return;

    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    setPlaybackRateInternal(playbackRate);
}

void Animation::setPlaybackRateInternal(double playbackRate)
{
    ASSERT(std::isfinite(playbackRate));
    ASSERT(playbackRate != m_playbackRate);

    if (!limited() && !paused() && hasStartTime())
        m_currentTimePending = true;

    double storedCurrentTime = currentTimeInternal();
    if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && playbackRate <= 0))
        m_finished = false;

    m_playbackRate = playbackRate;
    m_startTime = std::numeric_limits<double>::quiet_NaN();
    setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand);
}

void Animation::clearOutdated()
{
    if (!m_outdated)
        return;
    m_outdated = false;
    if (m_timeline)
        m_timeline->clearOutdatedAnimation(this);
}

void Animation::setOutdated()
{
    if (m_outdated)
        return;
    m_outdated = true;
    if (m_timeline)
        m_timeline->setOutdatedAnimation(this);
}

bool Animation::canStartAnimationOnCompositor() const
{
    if (m_isCompositedAnimationDisabledForTesting)
        return false;

    // FIXME: Timeline playback rates should be compositable
    if (m_playbackRate == 0 || (std::isinf(effectEnd()) && m_playbackRate < 0) || (timeline() && timeline()->playbackRate() != 1))
        return false;

    return m_timeline && m_content && m_content->isKeyframeEffect() && playing();
}

bool Animation::isCandidateForAnimationOnCompositor() const
{
    if (!canStartAnimationOnCompositor())
        return false;

    return toKeyframeEffect(m_content.get())->isCandidateForAnimationOnCompositor(m_playbackRate);
}

bool Animation::maybeStartAnimationOnCompositor()
{
    if (!canStartAnimationOnCompositor())
        return false;

    bool reversed = m_playbackRate < 0;

    double startTime = timeline()->zeroTime() + startTimeInternal();
    if (reversed) {
        startTime -= effectEnd() / fabs(m_playbackRate);
    }

    double timeOffset = 0;
    if (std::isnan(startTime)) {
        timeOffset = reversed ? effectEnd() - currentTimeInternal() : currentTimeInternal();
        timeOffset = timeOffset / fabs(m_playbackRate);
    }
    ASSERT(m_compositorGroup != 0);
    return toKeyframeEffect(m_content.get())->maybeStartAnimationOnCompositor(m_compositorGroup, startTime, timeOffset, m_playbackRate);
}

void Animation::setCompositorPending(bool effectChanged)
{
    // FIXME: KeyframeEffect could notify this directly?
    if (!hasActiveAnimationsOnCompositor()) {
        destroyCompositorPlayer();
        m_compositorState.release();
    }
    if (effectChanged && m_compositorState) {
        m_compositorState->effectChanged = true;
    }
    if (m_compositorPending || m_isPausedForTesting) {
        return;
    }
#if !ENABLE(OILPAN)
    if (!timeline() || !timeline()->document()) {
        return;
    }
#endif

    if (!m_compositorState || m_compositorState->effectChanged
        || !playing() || m_compositorState->playbackRate != m_playbackRate
        || m_compositorState->startTime != m_startTime) {
        m_compositorPending = true;
        timeline()->document()->compositorPendingAnimations().add(this);
    }
}

void Animation::cancelAnimationOnCompositor()
{
    if (hasActiveAnimationsOnCompositor())
        toKeyframeEffect(m_content.get())->cancelAnimationOnCompositor();

    destroyCompositorPlayer();
}

void Animation::restartAnimationOnCompositor()
{
    if (hasActiveAnimationsOnCompositor())
        toKeyframeEffect(m_content.get())->restartAnimationOnCompositor();
}

void Animation::cancelIncompatibleAnimationsOnCompositor()
{
    if (m_content && m_content->isKeyframeEffect())
        toKeyframeEffect(m_content.get())->cancelIncompatibleAnimationsOnCompositor();
}

bool Animation::hasActiveAnimationsOnCompositor()
{
    if (!m_content || !m_content->isKeyframeEffect())
        return false;

    return toKeyframeEffect(m_content.get())->hasActiveAnimationsOnCompositor();
}

bool Animation::update(TimingUpdateReason reason)
{
    if (!m_timeline)
        return false;

    PlayStateUpdateScope updateScope(*this, reason, DoNotSetCompositorPending);

    clearOutdated();
    bool idle = playStateInternal() == Idle;

    if (m_content) {
        double inheritedTime = idle || isNull(m_timeline->currentTimeInternal())
            ? nullValue()
            : currentTimeInternal();

        if (!isNull(inheritedTime)) {
            double timeForClipping = m_held && (!limited(inheritedTime) || isNull(m_startTime))
                // Use hold time when there is no start time.
                ? inheritedTime
                // Use calculated current time when the animation is limited.
                : calculateCurrentTime();
            if (clipped(timeForClipping))
                inheritedTime = nullValue();
        }
        // Special case for end-exclusivity when playing backwards.
        if (inheritedTime == 0 && m_playbackRate < 0)
            inheritedTime = -1;
        m_content->updateInheritedTime(inheritedTime, reason);
    }

    if ((idle || limited()) && !m_finished) {
        if (reason == TimingUpdateForAnimationFrame && (idle || hasStartTime())) {
            if (idle) {
                // TODO(dstockwell): Fire the cancel event.
            } else {
                const AtomicString& eventType = EventTypeNames::finish;
                if (executionContext() && hasEventListeners(eventType)) {
                    double eventCurrentTime = currentTimeInternal() * 1000;
                    m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, eventCurrentTime, timeline()->currentTime());
                    m_pendingFinishedEvent->setTarget(this);
                    m_pendingFinishedEvent->setCurrentTarget(this);
                    m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent);
                }
            }
            m_finished = true;
        }
    }
    ASSERT(!m_outdated);
    return !m_finished || std::isfinite(timeToEffectChange());
}

double Animation::timeToEffectChange()
{
    ASSERT(!m_outdated);
    if (!hasStartTime())
        return std::numeric_limits<double>::infinity();

    double currentTime = calculateCurrentTime();
    if (m_held) {
        if (limited(currentTime)) {
            if (m_playbackRate > 0 && m_endClip + effectEnd() > currentTime)
                return m_endClip + effectEnd() - currentTime;
            if (m_playbackRate < 0 && m_startClip <= currentTime)
                return m_startClip - currentTime;
        }
        return std::numeric_limits<double>::infinity();
    }

    if (!m_content)
        return -currentTimeInternal() / m_playbackRate;
    double result = m_playbackRate > 0
        ? m_content->timeToForwardsEffectChange() / m_playbackRate
        : m_content->timeToReverseEffectChange() / -m_playbackRate;

    return !hasActiveAnimationsOnCompositor() && m_content->phase() == AnimationEffect::PhaseActive
        ? 0
        : clipTimeToEffectChange(result);
}

double Animation::clipTimeToEffectChange(double result) const
{
    double currentTime = calculateCurrentTime();
    if (m_playbackRate > 0) {
        if (currentTime <= m_startClip)
            result = std::min(result, (m_startClip - currentTime) / m_playbackRate);
        else if (currentTime < m_endClip + effectEnd())
            result = std::min(result, (m_endClip + effectEnd() - currentTime) / m_playbackRate);
    } else {
        if (currentTime >= m_endClip + effectEnd())
            result = std::min(result, (currentTime - m_endClip + effectEnd()) / -m_playbackRate);
        else if (currentTime > m_startClip)
            result = std::min(result, (currentTime - m_startClip) / -m_playbackRate);
    }
    return result;
}

void Animation::cancel()
{
    PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);

    if (playStateInternal() == Idle)
        return;

    m_holdTime = currentTimeInternal();
    m_held = true;
    // TODO
    m_playState = Idle;
    m_startTime = nullValue();
    m_currentTimePending = false;

    if (timeline())
        InspectorInstrumentation::didCancelAnimation(timeline()->document(), this);
}

void Animation::beginUpdatingState()
{
    // Nested calls are not allowed!
    ASSERT(!m_stateIsBeingUpdated);
    m_stateIsBeingUpdated = true;
}

void Animation::endUpdatingState()
{
    ASSERT(m_stateIsBeingUpdated);
    m_stateIsBeingUpdated = false;
}

void Animation::createCompositorPlayer()
{
    if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled() && Platform::current()->isThreadedAnimationEnabled() && !m_compositorPlayer) {
        ASSERT(Platform::current()->compositorSupport());
        m_compositorPlayer = adoptPtr(Platform::current()->compositorSupport()->createAnimationPlayer());
        ASSERT(m_compositorPlayer);
        m_compositorPlayer->setAnimationDelegate(this);
        attachCompositorTimeline();
    }

    attachCompositedLayers();
}

void Animation::destroyCompositorPlayer()
{
    detachCompositedLayers();

    if (m_compositorPlayer) {
        detachCompositorTimeline();
        m_compositorPlayer->setAnimationDelegate(nullptr);
    }
    m_compositorPlayer.clear();
}

void Animation::attachCompositorTimeline()
{
    if (m_compositorPlayer) {
        WebCompositorAnimationTimeline* timeline = m_timeline ? m_timeline->compositorTimeline() : nullptr;
        if (timeline)
            timeline->playerAttached(*this);
    }
}

void Animation::detachCompositorTimeline()
{
    if (m_compositorPlayer) {
        WebCompositorAnimationTimeline* timeline = m_timeline ? m_timeline->compositorTimeline() : nullptr;
        if (timeline)
            timeline->playerDestroyed(*this);
    }
}

void Animation::attachCompositedLayers()
{
    if (!RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled() || !m_compositorPlayer)
        return;

    ASSERT(m_content);
    ASSERT(m_content->isKeyframeEffect());

    if (toKeyframeEffect(m_content.get())->canAttachCompositedLayers())
        toKeyframeEffect(m_content.get())->attachCompositedLayers();
}

void Animation::detachCompositedLayers()
{
    if (m_compositorPlayer && m_compositorPlayer->isLayerAttached())
        m_compositorPlayer->detachLayer();
}

void Animation::notifyAnimationStarted(double monotonicTime, int group)
{
    ASSERT(RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled());
    timeline()->document()->compositorPendingAnimations().notifyCompositorAnimationStarted(monotonicTime, group);
}

Animation::PlayStateUpdateScope::PlayStateUpdateScope(Animation& animation, TimingUpdateReason reason, CompositorPendingChange compositorPendingChange)
    : m_animation(animation)
    , m_initialPlayState(m_animation->playStateInternal())
    , m_compositorPendingChange(compositorPendingChange)
{
    m_animation->beginUpdatingState();
    m_animation->updateCurrentTimingState(reason);
}

Animation::PlayStateUpdateScope::~PlayStateUpdateScope()
{
    AnimationPlayState oldPlayState = m_initialPlayState;
    AnimationPlayState newPlayState = m_animation->calculatePlayState();

    m_animation->m_playState = newPlayState;
    if (oldPlayState != newPlayState) {
        bool wasActive = oldPlayState == Pending || oldPlayState == Running;
        bool isActive = newPlayState == Pending || newPlayState == Running;
        if (!wasActive && isActive)
            TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("blink.animations,devtools.timeline", "Animation", m_animation, "data", InspectorAnimationEvent::data(*m_animation));
        else if (wasActive && !isActive)
            TRACE_EVENT_NESTABLE_ASYNC_END1("blink.animations,devtools.timeline", "Animation", m_animation, "endData", InspectorAnimationStateEvent::data(*m_animation));
        else
            TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("blink.animations,devtools.timeline", "Animation", m_animation, "data", InspectorAnimationStateEvent::data(*m_animation));
    }

    // Ordering is important, the ready promise should resolve/reject before
    // the finished promise.
    if (m_animation->m_readyPromise && newPlayState != oldPlayState) {
        if (newPlayState == Idle) {
            if (m_animation->m_readyPromise->state() == AnimationPromise::Pending) {
                m_animation->m_readyPromise->reject(DOMException::create(AbortError));
            }
            m_animation->m_readyPromise->reset();
            m_animation->m_readyPromise->resolve(m_animation);
        } else if (oldPlayState == Pending) {
            m_animation->m_readyPromise->resolve(m_animation);
        } else if (newPlayState == Pending) {
            ASSERT(m_animation->m_readyPromise->state() != AnimationPromise::Pending);
            m_animation->m_readyPromise->reset();
        }
    }

    if (m_animation->m_finishedPromise && newPlayState != oldPlayState) {
        if (newPlayState == Idle) {
            if (m_animation->m_finishedPromise->state() == AnimationPromise::Pending) {
                m_animation->m_finishedPromise->reject(DOMException::create(AbortError));
            }
            m_animation->m_finishedPromise->reset();
        } else if (newPlayState == Finished) {
            m_animation->m_finishedPromise->resolve(m_animation);
        } else if (oldPlayState == Finished) {
            m_animation->m_finishedPromise->reset();
        }
    }

    if (oldPlayState != newPlayState && (oldPlayState == Idle || newPlayState == Idle)) {
        m_animation->setOutdated();
    }

#if ENABLE(ASSERT)
    // Verify that current time is up to date.
    m_animation->currentTimeInternal();
#endif

    switch (m_compositorPendingChange) {
    case SetCompositorPending:
        m_animation->setCompositorPending();
        break;
    case SetCompositorPendingWithEffectChanged:
        m_animation->setCompositorPending(true);
        break;
    case DoNotSetCompositorPending:
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }
    m_animation->endUpdatingState();

    if (oldPlayState != newPlayState && newPlayState == Running)
        InspectorInstrumentation::didStartAnimation(m_animation->timeline()->document(), m_animation);
}

bool Animation::addEventListener(const AtomicString& eventType, PassRefPtrWillBeRawPtr<EventListener> listener, bool useCapture)
{
    if (eventType == EventTypeNames::finish)
        UseCounter::count(executionContext(), UseCounter::AnimationFinishEvent);
    return EventTargetWithInlineData::addEventListener(eventType, listener, useCapture);
}

void Animation::pauseForTesting(double pauseTime)
{
    RELEASE_ASSERT(!paused());
    setCurrentTimeInternal(pauseTime, TimingUpdateOnDemand);
    if (hasActiveAnimationsOnCompositor())
        toKeyframeEffect(m_content.get())->pauseAnimationForTestingOnCompositor(currentTimeInternal());
    m_isPausedForTesting = true;
    pause();
}

void Animation::disableCompositedAnimationForTesting()
{
    m_isCompositedAnimationDisabledForTesting = true;
    cancelAnimationOnCompositor();
}

DEFINE_TRACE(Animation)
{
    visitor->trace(m_content);
    visitor->trace(m_timeline);
    visitor->trace(m_pendingFinishedEvent);
    visitor->trace(m_finishedPromise);
    visitor->trace(m_readyPromise);
    RefCountedGarbageCollectedEventTargetWithInlineData<Animation>::trace(visitor);
    ActiveDOMObject::trace(visitor);
}

} // namespace
