/*
 * Copyright (C) 2008-2019 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. 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 "SMILTimeContainer.h"

#include "Document.h"
#include "ElementIterator.h"
#include "Page.h"
#include "SVGSMILElement.h"
#include "SVGSVGElement.h"
#include "ScopedEventQueue.h"

namespace WebCore {

static const Seconds SMILAnimationFrameDelay { 1_s / 60. };
static const Seconds SMILAnimationFrameThrottledDelay { 1_s / 30. };

DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(SMILTimeContainer);

SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner)
    : m_timer(*this, &SMILTimeContainer::timerFired)
    , m_ownerSVGElement(owner)
{
}

void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
{
    ASSERT(animation->timeContainer() == this);
    ASSERT(target);
    ASSERT(animation->hasValidAttributeName());

    ElementAttributePair key(target, attributeName);
    auto& animations = m_scheduledAnimations.add(key, AnimationsVector()).iterator->value;
    ASSERT(!animations.contains(animation));
    animations.append(animation);

    SMILTime nextFireTime = animation->nextProgressTime();
    if (nextFireTime.isFinite())
        notifyIntervalsChanged();
}

void SMILTimeContainer::unschedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
{
    ASSERT(animation->timeContainer() == this);

    ElementAttributePair key(target, attributeName);
    auto& animations = m_scheduledAnimations.find(key)->value;
    ASSERT(animations.contains(animation));
    animations.removeFirst(animation);
}

void SMILTimeContainer::notifyIntervalsChanged()
{
    // Schedule updateAnimations() to be called asynchronously so multiple intervals
    // can change with updateAnimations() only called once at the end.
    startTimer(elapsed(), 0);
}

Seconds SMILTimeContainer::animationFrameDelay() const
{
    auto* page = m_ownerSVGElement.document().page();
    if (!page)
        return SMILAnimationFrameDelay;
    return page->isLowPowerModeEnabled() ? SMILAnimationFrameThrottledDelay : SMILAnimationFrameDelay;
}

SMILTime SMILTimeContainer::elapsed() const
{
    if (!m_beginTime)
        return 0_s;
    if (isPaused())
        return m_accumulatedActiveTime;
    return MonotonicTime::now() + m_accumulatedActiveTime - m_resumeTime;
}

bool SMILTimeContainer::isActive() const
{
    return !!m_beginTime && !isPaused();
}

bool SMILTimeContainer::isPaused() const
{
    return !!m_pauseTime;
}

bool SMILTimeContainer::isStarted() const
{
    return !!m_beginTime;
}

void SMILTimeContainer::begin()
{
    ASSERT(!m_beginTime);
    MonotonicTime now = MonotonicTime::now();

    // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began.
    // In this case pass on 'seekToTime=true' to updateAnimations().
    m_beginTime = m_resumeTime = now - m_presetStartTime;
    updateAnimations(SMILTime(m_presetStartTime), m_presetStartTime ? true : false);
    m_presetStartTime = 0_s;

    if (m_pauseTime) {
        m_pauseTime = now;
        m_timer.stop();
    }
}

void SMILTimeContainer::pause()
{
    ASSERT(!isPaused());

    m_pauseTime = MonotonicTime::now();
    if (m_beginTime) {
        m_accumulatedActiveTime += m_pauseTime - m_resumeTime;
        m_timer.stop();
    }
}

void SMILTimeContainer::resume()
{
    ASSERT(isPaused());

    m_resumeTime = MonotonicTime::now();
    m_pauseTime = MonotonicTime();
    startTimer(elapsed(), 0);
}

void SMILTimeContainer::setElapsed(SMILTime time)
{
    // If the documment didn't begin yet, record a new start time, we'll seek to once its possible.
    if (!m_beginTime) {
        m_presetStartTime = Seconds(time.value());
        return;
    }

    if (m_beginTime)
        m_timer.stop();

    MonotonicTime now = MonotonicTime::now();
    m_beginTime = now - Seconds { time.value() };

    if (m_pauseTime) {
        m_resumeTime = m_pauseTime = now;
        m_accumulatedActiveTime = Seconds(time.value());
    } else
        m_resumeTime = m_beginTime;

    processScheduledAnimations([](auto& animation) {
        animation.reset();
    });

    updateAnimations(time, true);
}

void SMILTimeContainer::startTimer(SMILTime elapsed, SMILTime fireTime, SMILTime minimumDelay)
{
    if (!m_beginTime || isPaused())
        return;

    if (!fireTime.isFinite())
        return;

    SMILTime delay = std::max(fireTime - elapsed, minimumDelay);
    m_timer.startOneShot(1_s * delay.value());
}

void SMILTimeContainer::timerFired()
{
    ASSERT(!!m_beginTime);
    ASSERT(!m_pauseTime);
    updateAnimations(elapsed());
}

void SMILTimeContainer::updateDocumentOrderIndexes()
{
    unsigned timingElementCount = 0;

    for (auto& smilElement : descendantsOfType<SVGSMILElement>(m_ownerSVGElement))
        smilElement.setDocumentOrderIndex(timingElementCount++);

    m_documentOrderIndexesDirty = false;
}

struct PriorityCompare {
    PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {}
    bool operator()(SVGSMILElement* a, SVGSMILElement* b)
    {
        // FIXME: This should also consider possible timing relations between the elements.
        SMILTime aBegin = a->intervalBegin();
        SMILTime bBegin = b->intervalBegin();
        // Frozen elements need to be prioritized based on their previous interval.
        aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin() : aBegin;
        bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin() : bBegin;
        if (aBegin == bBegin)
            return a->documentOrderIndex() < b->documentOrderIndex();
        return aBegin < bBegin;
    }
    SMILTime m_elapsed;
};

void SMILTimeContainer::sortByPriority(AnimationsVector& animations, SMILTime elapsed)
{
    if (m_documentOrderIndexesDirty)
        updateDocumentOrderIndexes();
    std::sort(animations.begin(), animations.end(), PriorityCompare(elapsed));
}

void SMILTimeContainer::processScheduledAnimations(const Function<void(SVGSMILElement&)>& callback)
{
    for (auto& animations : copyToVector(m_scheduledAnimations.values())) {
        for (auto* animation : animations)
            callback(*animation);
    }
}

void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
{
    // Don't mutate the DOM while updating the animations.
    EventQueueScope scope;

    processScheduledAnimations([](auto& animation) {
        if (!animation.hasConditionsConnected())
            animation.connectConditions();
    });

    AnimationsVector animationsToApply;
    SMILTime earliestFireTime = SMILTime::unresolved();

    for (auto& animations : copyToVector(m_scheduledAnimations.values())) {
        // Sort according to priority. Elements with later begin time have higher priority.
        // In case of a tie, document order decides.
        // FIXME: This should also consider timing relationships between the elements. Dependents
        // have higher priority.
        sortByPriority(animations, elapsed);

        RefPtr<SVGSMILElement> firstAnimation;
        for (auto* animation : animations) {
            ASSERT(animation->timeContainer() == this);
            ASSERT(animation->targetElement());
            ASSERT(animation->hasValidAttributeName());

            // Results are accumulated to the first animation that animates and contributes to a particular element/attribute pair.
            if (!firstAnimation) {
                if (!animation->hasValidAttributeType())
                    return;
                firstAnimation = animation;
            }

            // This will calculate the contribution from the animation and add it to the resultsElement.
            if (!animation->progress(elapsed, *firstAnimation, seekToTime) && firstAnimation == animation)
                firstAnimation = nullptr;

            SMILTime nextFireTime = animation->nextProgressTime();
            if (nextFireTime.isFinite())
                earliestFireTime = std::min(nextFireTime, earliestFireTime);
        }

        if (firstAnimation)
            animationsToApply.append(firstAnimation.get());
    }

    // Apply results to target elements.
    for (auto& animation : animationsToApply)
        animation->applyResultsToTarget();

    startTimer(elapsed, earliestFireTime, animationFrameDelay());
}

}
