/*
    Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
                  2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
    Copyright (C) 2007 Eric Seidel <eric@webkit.org>
    Copyright (C) 2008 Apple Inc. All rights reserved.

    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., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "config.h"

#if ENABLE(SVG_ANIMATION)
#include "SVGAnimationElement.h"

#include "CSSComputedStyleDeclaration.h"
#include "CSSParser.h"
#include "CSSPropertyNames.h"
#include "Document.h"
#include "Event.h"
#include "EventListener.h"
#include "FloatConversion.h"
#include "HTMLNames.h"
#include "MappedAttribute.h"
#include "SVGElementInstance.h"
#include "SVGNames.h"
#include "SVGURIReference.h"
#include "SVGUseElement.h"
#include "XLinkNames.h"
#include <math.h>
#include <wtf/StdLibExtras.h>

using namespace std;

namespace WebCore {
    
SVGAnimationElement::SVGAnimationElement(const QualifiedName& tagName, Document* doc)
    : SVGSMILElement(tagName, doc)
    , SVGTests()
    , SVGExternalResourcesRequired()
    , m_animationValid(false)
{
}

SVGAnimationElement::~SVGAnimationElement()
{
}
    
static void parseKeyTimes(const String& parse, Vector<float>& result, bool verifyOrder)
{
    result.clear();
    Vector<String> parseList;
    parse.split(';', parseList);
    for (unsigned n = 0; n < parseList.size(); ++n) {
        String timeString = parseList[n];
        bool ok;
        float time = timeString.toFloat(&ok);
        if (!ok || time < 0 || time > 1.f)
            goto fail;
        if (verifyOrder) {
            if (!n) {
                if (time != 0)
                    goto fail;
            } else if (time < result.last())
                goto fail;
        }
        result.append(time);
    }
    return;
fail:
    result.clear();
}

static void parseKeySplines(const String& parse, Vector<UnitBezier>& result)
{
    result.clear();
    Vector<String> parseList;
    parse.split(';', parseList);
    for (unsigned n = 0; n < parseList.size(); ++n) {
        Vector<String> parseSpline;
        parseList[n].split(',', parseSpline);
        // The spec says the sepator is a space, all tests use commas. Weird.
        if (parseSpline.size() == 1) 
            parseList[n].split(' ', parseSpline);
        if (parseSpline.size() != 4)
            goto fail;
        double curveValues[4];
        for (unsigned i = 0; i < 4; ++i) {
            String parseNumber = parseSpline[i]; 
            bool ok;
            curveValues[i] = parseNumber.toDouble(&ok);
            if (!ok || curveValues[i] < 0.0 || curveValues[i] > 1.0)
                goto fail;
        }
        result.append(UnitBezier(curveValues[0], curveValues[1], curveValues[2], curveValues[3]));
    }
    return;
fail:
    result.clear();
}

void SVGAnimationElement::parseMappedAttribute(MappedAttribute* attr)
{
    if (attr->name() == SVGNames::valuesAttr)
        attr->value().string().split(';', m_values);
    else if (attr->name() == SVGNames::keyTimesAttr)
        parseKeyTimes(attr->value(), m_keyTimes, true);
    else if (attr->name() == SVGNames::keyPointsAttr && hasTagName(SVGNames::animateMotionTag)) {
        // This is specified to be an animateMotion attribute only but it is simpler to put it here 
        // where the other timing calculatations are.
        parseKeyTimes(attr->value(), m_keyPoints, false);
    } else if (attr->name() == SVGNames::keySplinesAttr)
        parseKeySplines(attr->value(), m_keySplines);
    else {
        if (SVGTests::parseMappedAttribute(attr))
            return;
        if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
            return;
        SVGSMILElement::parseMappedAttribute(attr);
    }
}

void SVGAnimationElement::attributeChanged(Attribute* attr, bool preserveDecls)
{
    // Assumptions may not hold after an attribute change.
    m_animationValid = false;
    SVGSMILElement::attributeChanged(attr, preserveDecls);
}

float SVGAnimationElement::getStartTime() const
{
    return narrowPrecisionToFloat(intervalBegin().value());
}

float SVGAnimationElement::getCurrentTime() const
{
    return narrowPrecisionToFloat(elapsed().value());
}

float SVGAnimationElement::getSimpleDuration(ExceptionCode&) const
{
    return narrowPrecisionToFloat(simpleDuration().value());
}    
    
bool SVGAnimationElement::beginElement(ExceptionCode& ec)
{
    return beginElementAt(0, ec);
}

bool SVGAnimationElement::beginElementAt(float offset, ExceptionCode&)
{
    addBeginTime(elapsed() + offset);
    return true;
}

bool SVGAnimationElement::endElement(ExceptionCode& ec)
{
    return endElementAt(0, ec);
}

bool SVGAnimationElement::endElementAt(float offset, ExceptionCode&)
{
    if (offset < 0)
        return false;
    
    addEndTime(elapsed() + offset);
    return true;
}

SVGAnimationElement::AnimationMode SVGAnimationElement::animationMode() const
{
    // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#AnimFuncValues
    if (hasTagName(SVGNames::setTag))
        return ToAnimation;
    if (!animationPath().isEmpty())
        return PathAnimation;
    if (hasAttribute(SVGNames::valuesAttr))
        return ValuesAnimation;
    if (!toValue().isEmpty())
        return fromValue().isEmpty() ? ToAnimation : FromToAnimation;
    if (!byValue().isEmpty())
        return fromValue().isEmpty() ? ByAnimation : FromByAnimation;
    return NoAnimation;
}

SVGAnimationElement::CalcMode SVGAnimationElement::calcMode() const
{    
    DEFINE_STATIC_LOCAL(const AtomicString, discrete, ("discrete"));
    DEFINE_STATIC_LOCAL(const AtomicString, linear, ("linear"));
    DEFINE_STATIC_LOCAL(const AtomicString, paced, ("paced"));
    DEFINE_STATIC_LOCAL(const AtomicString, spline, ("spline"));
    const AtomicString& value = getAttribute(SVGNames::calcModeAttr);
    if (value == discrete)
        return CalcModeDiscrete;
    if (value == linear)
        return CalcModeLinear;
    if (value == paced)
        return CalcModePaced;
    if (value == spline)
        return CalcModeSpline;
    return hasTagName(SVGNames::animateMotionTag) ? CalcModePaced : CalcModeLinear;
}

SVGAnimationElement::AttributeType SVGAnimationElement::attributeType() const
{    
    DEFINE_STATIC_LOCAL(const AtomicString, css, ("CSS"));
    DEFINE_STATIC_LOCAL(const AtomicString, xml, ("XML"));
    const AtomicString& value = getAttribute(SVGNames::attributeTypeAttr);
    if (value == css)
        return AttributeTypeCSS;
    if (value == xml)
        return AttributeTypeXML;
    return AttributeTypeAuto;
}

String SVGAnimationElement::toValue() const
{    
    return getAttribute(SVGNames::toAttr);
}

String SVGAnimationElement::byValue() const
{    
    return getAttribute(SVGNames::byAttr);
}

String SVGAnimationElement::fromValue() const
{    
    return getAttribute(SVGNames::fromAttr);
}

bool SVGAnimationElement::isAdditive() const
{
    DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum"));
    const AtomicString& value = getAttribute(SVGNames::additiveAttr);
    return value == sum || animationMode() == ByAnimation;
}

bool SVGAnimationElement::isAccumulated() const
{
    DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum"));
    const AtomicString& value = getAttribute(SVGNames::accumulateAttr);
    return value == sum && animationMode() != ToAnimation;
}

bool SVGAnimationElement::hasValidTarget() const
{
    return targetElement();
}
    
bool SVGAnimationElement::attributeIsCSS(const String& attributeName)
{
    // FIXME: We should have a map of all SVG properties and their attribute types so we
    // could validate animations better. The spec is very vague about this.
    unsigned id = cssPropertyID(attributeName);
    // SVG range
    if (id >= CSSPropertyClipPath && id <= CSSPropertyWritingMode)
        return true;
    // Regular CSS properties also in SVG
    return id == CSSPropertyColor || id == CSSPropertyDisplay || id == CSSPropertyOpacity
            || (id >= CSSPropertyFont && id <= CSSPropertyFontWeight) 
            || id == CSSPropertyOverflow || id == CSSPropertyVisibility;
}
    
bool SVGAnimationElement::targetAttributeIsCSS() const
{
    AttributeType type = attributeType();
    if (type == AttributeTypeCSS)
        return true;
    if (type == AttributeTypeXML)
        return false;
    return attributeIsCSS(attributeName());
}

void SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value)
{
    if (!hasValidTarget())
        return;
    SVGElement* target = targetElement();
    String attributeName = this->attributeName();
    if (!target || attributeName.isEmpty() || value.isNull())
        return;

    // We don't want the instance tree to get rebuild. Instances are updated in the loop below.
    if (target->isStyled())
        static_cast<SVGStyledElement*>(target)->setInstanceUpdatesBlocked(true);
        
    ExceptionCode ec;
    bool isCSS = targetAttributeIsCSS();
    if (isCSS) {
        // FIXME: This should set the override style, not the inline style.
        // Sadly override styles are not yet implemented.
        target->style()->setProperty(attributeName, value, "", ec);
    } else {
        // FIXME: This should set the 'presentation' value, not the actual 
        // attribute value. Whatever that means in practice.
        target->setAttribute(attributeName, value, ec);
    }
    
    if (target->isStyled())
        static_cast<SVGStyledElement*>(target)->setInstanceUpdatesBlocked(false);
    
    // If the target element is used in an <use> instance tree, update that as well.
    HashSet<SVGElementInstance*> instances = target->instancesForElement();
    HashSet<SVGElementInstance*>::iterator end = instances.end();
    for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) {
        SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
        ASSERT(shadowTreeElement);
        if (isCSS)
            shadowTreeElement->style()->setProperty(attributeName, value, "", ec);
        else
            shadowTreeElement->setAttribute(attributeName, value, ec);
        (*it)->correspondingUseElement()->setNeedsStyleRecalc();
    }
}
    
void SVGAnimationElement::calculateKeyTimesForCalcModePaced()
{
    ASSERT(calcMode() == CalcModePaced);
    ASSERT(animationMode() == ValuesAnimation);

    unsigned valuesCount = m_values.size();
    ASSERT(valuesCount > 1);
    Vector<float> keyTimesForPaced;
    float totalDistance = 0;
    keyTimesForPaced.append(0);
    for (unsigned n = 0; n < valuesCount - 1; ++n) {
        // Distance in any units
        float distance = calculateDistance(m_values[n], m_values[n + 1]);
        if (distance < 0)
            return;
        totalDistance += distance;
        keyTimesForPaced.append(distance);
    }
    if (!totalDistance)
        return;

    // Normalize.
    for (unsigned n = 1; n < keyTimesForPaced.size() - 1; ++n)
        keyTimesForPaced[n] = keyTimesForPaced[n - 1] + keyTimesForPaced[n] / totalDistance;
    keyTimesForPaced[keyTimesForPaced.size() - 1] = 1.f;

    // Use key times calculated based on pacing instead of the user provided ones.
    m_keyTimes.swap(keyTimesForPaced);
}

static inline double solveEpsilon(double duration) { return 1. / (200. * duration); }
    
float SVGAnimationElement::calculatePercentForSpline(float percent, unsigned splineIndex) const
{
    ASSERT(calcMode() == CalcModeSpline);
    ASSERT(splineIndex < m_keySplines.size());
    UnitBezier bezier = m_keySplines[splineIndex];
    SMILTime duration = simpleDuration();
    if (!duration.isFinite())
        duration = 100.0;
    return narrowPrecisionToFloat(bezier.solve(percent, solveEpsilon(duration.value())));
}

float SVGAnimationElement::calculatePercentFromKeyPoints(float percent) const
{
    ASSERT(!m_keyPoints.isEmpty());
    ASSERT(calcMode() != CalcModePaced);
    unsigned keyTimesCount = m_keyTimes.size();
    ASSERT(keyTimesCount > 1);
    ASSERT(m_keyPoints.size() == keyTimesCount);

    unsigned index;
    for (index = 1; index < keyTimesCount; ++index) {
        if (m_keyTimes[index] >= percent)
            break;
    }
    --index;

    float fromPercent = m_keyTimes[index];
    float toPercent = m_keyTimes[index + 1];
    float fromKeyPoint = m_keyPoints[index];
    float toKeyPoint = m_keyPoints[index + 1];
    
    if (calcMode() == CalcModeDiscrete)
        return percent == 1.0f ? toKeyPoint : fromKeyPoint;
    
    float keyPointPercent = percent == 1.0f ? 1.0f : (percent - fromPercent) / (toPercent - fromPercent);
    
    if (calcMode() == CalcModeSpline) {
        ASSERT(m_keySplines.size() == m_keyPoints.size() - 1);
        keyPointPercent = calculatePercentForSpline(keyPointPercent, index);
    }
    return (toKeyPoint - fromKeyPoint) * keyPointPercent + fromKeyPoint;
}
    
void SVGAnimationElement::currentValuesFromKeyPoints(float percent, float& effectivePercent, String& from, String& to) const
{
    ASSERT(!m_keyPoints.isEmpty());
    ASSERT(m_keyPoints.size() == m_keyTimes.size());
    ASSERT(calcMode() != CalcModePaced);
    effectivePercent = calculatePercentFromKeyPoints(percent);
    unsigned index = effectivePercent == 1.0f ? m_values.size() - 2 : static_cast<unsigned>(effectivePercent * (m_values.size() - 1));
    from = m_values[index];
    to = m_values[index + 1];
}
    
void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to) const
{
    unsigned valuesCount = m_values.size();
    ASSERT(m_animationValid);
    ASSERT(valuesCount > 1);
    
    CalcMode calcMode = this->calcMode();
    if (!m_keyPoints.isEmpty() && calcMode != CalcModePaced)
        return currentValuesFromKeyPoints(percent, effectivePercent, from, to);
    
    unsigned keyTimesCount = m_keyTimes.size();
    ASSERT(!keyTimesCount || valuesCount == keyTimesCount);
    ASSERT(!keyTimesCount || (keyTimesCount > 1 && m_keyTimes[0] == 0));

    unsigned index;
    for (index = 1; index < keyTimesCount; ++index) {
        if (m_keyTimes[index] >= percent)
            break;
    }
    --index;
    
    if (calcMode == CalcModeDiscrete) {
        if (!keyTimesCount) 
            index = percent == 1.0f ? valuesCount - 1 : static_cast<unsigned>(percent * valuesCount);
        from = m_values[index];
        to = m_values[index];
        effectivePercent = 0.0f;
        return;
    }
    
    float fromPercent;
    float toPercent;
    if (keyTimesCount) {
        fromPercent = m_keyTimes[index];
        toPercent = m_keyTimes[index + 1];
    } else {        
        index = static_cast<unsigned>(percent * (valuesCount - 1));
        fromPercent =  static_cast<float>(index) / (valuesCount - 1);
        toPercent =  static_cast<float>(index + 1) / (valuesCount - 1);
    }
    
    if (index == valuesCount - 1)
        --index;
    from = m_values[index];
    to = m_values[index + 1];
    ASSERT(toPercent > fromPercent);
    effectivePercent = percent == 1.0f ? 1.0f : (percent - fromPercent) / (toPercent - fromPercent);
    
    if (calcMode == CalcModeSpline) {
        ASSERT(m_keySplines.size() == m_values.size() - 1);
        effectivePercent = calculatePercentForSpline(effectivePercent, index);
    }
}
    
void SVGAnimationElement::startedActiveInterval()
{
    m_animationValid = false;

    if (!hasValidTarget())
        return;

    AnimationMode animationMode = this->animationMode();
    if (animationMode == NoAnimation)
        return;
    if (animationMode == FromToAnimation)
        m_animationValid = calculateFromAndToValues(fromValue(), toValue());
    else if (animationMode == ToAnimation) {
        // For to-animations the from value is the current accumulated value from lower priority animations.
        // The value is not static and is determined during the animation.
        m_animationValid = calculateFromAndToValues(String(), toValue());
    } else if (animationMode == FromByAnimation)
        m_animationValid = calculateFromAndByValues(fromValue(), byValue());
    else if (animationMode == ByAnimation)
        m_animationValid = calculateFromAndByValues(String(), byValue());
    else if (animationMode == ValuesAnimation) {
        CalcMode calcMode = this->calcMode();
        m_animationValid = m_values.size() > 1
            && (calcMode == CalcModePaced || !hasAttribute(SVGNames::keyTimesAttr) || hasAttribute(SVGNames::keyPointsAttr) || (m_values.size() == m_keyTimes.size()))
            && (calcMode == CalcModeDiscrete || !m_keyTimes.size() || m_keyTimes.last() == 1.0)
            && (calcMode != CalcModeSpline || (m_keySplines.size() && (m_keySplines.size() == m_values.size() - 1) || m_keySplines.size() == m_keyPoints.size() - 1))
            && (!hasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size()));
        if (calcMode == CalcModePaced && m_animationValid)
            calculateKeyTimesForCalcModePaced();
    } else if (animationMode == PathAnimation)
        m_animationValid = calcMode() == CalcModePaced || !hasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size());
}
    
void SVGAnimationElement::updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement)
{    
    if (!m_animationValid)
        return;
    
    float effectivePercent;
    if (animationMode() == ValuesAnimation) {
        String from;
        String to;
        currentValuesForValuesAnimation(percent, effectivePercent, from, to);
        if (from != m_lastValuesAnimationFrom || to != m_lastValuesAnimationTo ) {
            m_animationValid = calculateFromAndToValues(from, to);
            if (!m_animationValid)
                return;
            m_lastValuesAnimationFrom = from;
            m_lastValuesAnimationTo = to;
        }
    } else if (!m_keyPoints.isEmpty() && calcMode() != CalcModePaced)
        effectivePercent = calculatePercentFromKeyPoints(percent);
    else 
        effectivePercent = percent;

    calculateAnimatedValue(effectivePercent, repeat, resultElement);
}

void SVGAnimationElement::endedActiveInterval()
{
}

}

// vim:ts=4:noet
#endif // ENABLE(SVG_ANIMATION)

