/*
    Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
                  2004, 2005 Rob Buis <buis@kde.org>
    Copyright (C) 2006 Apple Computer, Inc.

    This file is part of the KDE project

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "config.h"
#ifdef SVG_SUPPORT
#include "KSVGTimeScheduler.h"

#include "Document.h"
#include "SVGAnimateColorElement.h"
#include "SVGAnimateTransformElement.h"
#include "SVGTransformList.h"
#include "SVGDOMImplementation.h"
#include "SVGMatrix.h"
#include "SVGNames.h"
#include "SVGStyledElement.h"
#include "SVGStyledTransformableElement.h"
#include "SystemTime.h"
#include "Timer.h"

namespace WebCore {

const double staticTimerInterval = 0.050; // 50 ms

typedef HashSet<SVGAnimationElement*> SVGNotifySet;

class SVGTimer : private Timer<TimeScheduler>
{
public:
    SVGTimer(TimeScheduler*, double interval, bool singleShot);

    void start();
    using Timer<TimeScheduler>::stop;
    using Timer<TimeScheduler>::isActive;

    void notifyAll();
    void addNotify(SVGAnimationElement*, bool enabled = false);
    void removeNotify(SVGAnimationElement*);

    static SVGTimer* downcast(Timer<TimeScheduler>* t) { return static_cast<SVGTimer*>(t); }

private:
    double calculateTimePercentage(double elapsed, double start, double end, double duration, double repetitions);

    TimeScheduler* m_scheduler;
    double m_interval;
    bool m_singleShot;

    SVGNotifySet m_notifySet;
    SVGNotifySet m_enabledNotifySet;
};

SVGTimer::SVGTimer(TimeScheduler* scheduler, double interval, bool singleShot)
    : Timer<TimeScheduler>(scheduler, &TimeScheduler::timerFired)
    , m_scheduler(scheduler), m_interval(interval), m_singleShot(singleShot)
{
}

void SVGTimer::start()
{
    if (m_singleShot)
        startOneShot(m_interval);
    else
        startRepeating(m_interval);
}

double SVGTimer::calculateTimePercentage(double elapsed, double start, double end, double duration, double repetitions)
{
    double percentage = 0.0;

    double useElapsed = elapsed - (duration * repetitions);
    
    if (duration > 0.0 && end == 0.0)
        percentage = 1.0 - (((start + duration) - useElapsed) / duration);
    else if (duration > 0.0 && end != 0.0) {
        if (duration > end)
            percentage = 1.0 - (((start + end) - useElapsed) / end);
        else
            percentage = 1.0 - (((start + duration) - useElapsed) / duration);
    } else if(duration == 0.0 && end != 0.0)
        percentage = 1.0 - (((start + end) - useElapsed) / end);

    return percentage;
}

void SVGTimer::notifyAll()
{
    if (m_enabledNotifySet.isEmpty())
        return;

    double elapsed = m_scheduler->elapsed() * 1000.0; // Take time now.

    // First build a list of animation elements per target element
    // This is important to decide about the order & priority of 
    // the animations -> 'additive' support is handled this way.
    typedef HashMap<SVGElement*, Vector<SVGAnimationElement*> > TargetAnimationMap;
    TargetAnimationMap targetMap;
    
    SVGNotifySet::const_iterator end = m_notifySet.end();
    for (SVGNotifySet::const_iterator it = m_notifySet.begin(); it != end; ++it) {
        SVGAnimationElement* animation = *it;

        // If we're dealing with a disabled element with fill="freeze",
        // we have to take it into account for further calculations.
        if (!m_enabledNotifySet.contains(animation)) {
            if (!animation->isFrozen())
                continue;
            if (elapsed <= (animation->getStartTime() + animation->getSimpleDuration()))
                continue;
        }

        SVGElement* target = const_cast<SVGElement *>(animation->targetElement());
        TargetAnimationMap::iterator i = targetMap.find(target);
        if (i != targetMap.end())
            i->second.append(animation);
        else {
            Vector<SVGAnimationElement*> list;
            list.append(animation);
            targetMap.set(target, list);
        }
    }

    TargetAnimationMap::iterator targetIterator = targetMap.begin();
    TargetAnimationMap::iterator tend = targetMap.end();
    for (; targetIterator != tend; ++targetIterator) {
        HashMap<String, Color> targetColor; // special <animateColor> case
        RefPtr<SVGTransformList> targetTransforms; // special <animateTransform> case    

        unsigned count = targetIterator->second.size();
        for (unsigned i = 0; i < count; ++i) {
            SVGAnimationElement* animation = targetIterator->second[i];

            double end = animation->getEndTime();
            double start = animation->getStartTime();
            double duration = animation->getSimpleDuration();
            double repetitions = animation->repeations();

            // Validate animation timing settings:
            // #1 (duration > 0) -> fine
            // #2 (duration <= 0.0 && end > 0) -> fine
            
            if((duration <= 0.0 && end <= 0.0) ||
               (animation->isIndefinite(duration) && end <= 0.0)) // Ignore dur="0" or dur="-neg"
                continue;
            
            float percentage = calculateTimePercentage(elapsed, start, end, duration, repetitions);
                
            if(percentage <= 1.0 || animation->connected())
                animation->handleTimerEvent(percentage);

// FIXME: Disable animateTransform until SVGList can be fixed.
#if 0
            // Special cases for animate* objects depending on 'additive' attribute
            if(animation->hasTagName(SVGNames::animateTransformTag))
            {
                SVGAnimateTransformElement *animTransform = static_cast<SVGAnimateTransformElement *>(animation);
                if(!animTransform)
                    continue;

                RefPtr<SVGMatrix> transformMatrix = animTransform->transformMatrix();
                if(!transformMatrix)
                    continue;

                RefPtr<SVGMatrix> initialMatrix = animTransform->initialMatrix();
                RefPtr<SVGTransform> data = new SVGTransform();

                if(!targetTransforms) // lazy creation, only if needed.
                {
                    targetTransforms = new SVGTransformList();

                    if(animation->isAdditive() && initialMatrix)
                    {
                        RefPtr<SVGMatrix> matrix = new SVGMatrix(initialMatrix->matrix());
                        
                        data->setMatrix(matrix.get());
                        targetTransforms->appendItem(data.get());

                        data = new SVGTransform();
                    }
                }

                if(targetTransforms->numberOfItems() <= 1)
                    data->setMatrix(transformMatrix.get());
                else
                {
                    if(!animation->isAdditive())
                        targetTransforms->clear();    
                    
                    data->setMatrix(transformMatrix.get());
                }

                targetTransforms->appendItem(data.get());
            }
            else
#endif
            if(animation->hasTagName(SVGNames::animateColorTag))
            {
                SVGAnimateColorElement *animColor = static_cast<SVGAnimateColorElement *>(animation);
                if(!animColor)
                    continue;

                String name = animColor->attributeName();
                Color color = animColor->color();

                if(!targetColor.contains(name))
                {
                    if(animation->isAdditive())
                    {
                        int r = animColor->initialColor().red() + color.red();
                        int g = animColor->initialColor().green() + color.green();
                        int b = animColor->initialColor().blue() + color.blue();
                    
                        targetColor.set(name, animColor->clampColor(r, g, b));
                    }
                    else
                        targetColor.set(name, color);
                }
                else
                {
                    if(!animation->isAdditive())
                        targetColor.set(name, color);
                    else
                    {
                        Color baseColor = targetColor.get(name);
                        int r = baseColor.red() + color.red();
                        int g = baseColor.green() + color.green();
                        int b = baseColor.blue() + color.blue();

                        targetColor.set(name, animColor->clampColor(r, g, b));
                    }
                }
            }
        }

        // Handle <animateTransform>.
        if (targetTransforms) {
            SVGElement* key = targetIterator->first;
            if (key && key->isStyled() && key->isStyledTransformable()) {
                SVGStyledTransformableElement *transform = static_cast<SVGStyledTransformableElement *>(key);
                transform->setTransform(targetTransforms.get());
                transform->updateLocalTransform(transform->transform());
            }
        }

        // Handle <animateColor>.
        HashMap<String, Color>::iterator cend = targetColor.end();
        for(HashMap<String, Color>::iterator cit = targetColor.begin(); cit != cend; ++cit)
        {
            if(cit->second.isValid())
            {
                SVGAnimationElement::setTargetAttribute(targetIterator->first,
                                                            cit->first.impl(),
                                                            String(cit->second.name()).impl());
            }
        }
    }

    // Make a second pass through the map to avoid multiple setChanged calls on the same element.
    for (targetIterator = targetMap.begin(); targetIterator != tend; ++targetIterator) {
        SVGElement *key = targetIterator->first;
        if (key && key->isStyled())
            static_cast<SVGStyledElement *>(key)->setChanged(true);
    }
}

void SVGTimer::addNotify(SVGAnimationElement* element, bool enabled)
{
    m_notifySet.add(element);
    if (enabled)
        m_enabledNotifySet.add(element);
    else
        m_enabledNotifySet.remove(element);
}

void SVGTimer::removeNotify(SVGAnimationElement *element)
{
    // FIXME: Why do we keep a pointer to the element forever (marked disabled)?
    // That can't be right!

    m_enabledNotifySet.remove(element);
    if (m_enabledNotifySet.isEmpty())
        stop();
}

TimeScheduler::TimeScheduler(Document *document)
    : m_creationTime(currentTime()), m_savedTime(0), m_document(document)
{
    // Don't start this timer yet.
    m_intervalTimer = new SVGTimer(this, staticTimerInterval, false);
}

TimeScheduler::~TimeScheduler()
{
    deleteAllValues(m_timerSet);
    delete m_intervalTimer;
}

void TimeScheduler::addTimer(SVGAnimationElement* element, unsigned ms)
{
    SVGTimer* svgTimer = new SVGTimer(this, ms * 0.001, true);
    svgTimer->addNotify(element, true);
    m_timerSet.add(svgTimer);
    m_intervalTimer->addNotify(element, false);
}

void TimeScheduler::connectIntervalTimer(SVGAnimationElement* element)
{
    m_intervalTimer->addNotify(element, true);
}

void TimeScheduler::disconnectIntervalTimer(SVGAnimationElement* element)
{
    m_intervalTimer->removeNotify(element);
}

void TimeScheduler::startAnimations()
{
    m_creationTime = currentTime();

    SVGTimerSet::iterator end = m_timerSet.end();
    for (SVGTimerSet::iterator it = m_timerSet.begin(); it != end; ++it) {
        SVGTimer* svgTimer = *it;
        if (svgTimer && !svgTimer->isActive())
            svgTimer->start();
    }
}

void TimeScheduler::toggleAnimations()
{
    if (m_intervalTimer->isActive()) {
        m_intervalTimer->stop();
        m_savedTime = currentTime();
    } else {
        if (m_savedTime != 0) {
            m_creationTime += currentTime() - m_savedTime;
            m_savedTime = 0;
        }
        m_intervalTimer->start();
    }
}

bool TimeScheduler::animationsPaused() const
{
    return !m_intervalTimer->isActive();
}

void TimeScheduler::timerFired(Timer<TimeScheduler>* baseTimer)
{
    // Get the pointer now, because notifyAll could make the document,
    // including this TimeScheduler, go away.
    RefPtr<Document> doc = m_document;

    SVGTimer* timer = SVGTimer::downcast(baseTimer);

    timer->notifyAll();

    // FIXME: Is it really safe to look at m_intervalTimer now?
    // Isn't it possible the TimeScheduler was deleted already?
    // If so, timer, m_timerSet, and m_intervalTimer have all
    // been deleted. May need to reference count the TimeScheduler
    // to work around this, and ref/deref it in this function.
    if (timer != m_intervalTimer) {
        ASSERT(!timer->isActive());
        ASSERT(m_timerSet.contains(timer));
        m_timerSet.remove(timer);
        delete timer;

        // The singleShot timers of ie. <animate> with begin="3s" are notified
        // by the previous call, and now all connections to the interval timer
        // are created and now we just need to fire that timer (Niko)
        if (!m_intervalTimer->isActive())
            m_intervalTimer->start();
    }

    // Update any 'dirty' shapes.
    doc->updateRendering();
}

double TimeScheduler::elapsed() const
{
    return currentTime() - m_creationTime;
}

} // namespace

// vim:ts=4:noet
#endif // SVG_SUPPORT
