/*
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * 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.
 */

#ifndef SVGAnimatedListPropertyTearOff_h
#define SVGAnimatedListPropertyTearOff_h

#include "core/svg/properties/SVGAnimatedProperty.h"
#include "core/svg/properties/SVGListPropertyTearOff.h"
#include "core/svg/properties/SVGStaticListPropertyTearOff.h"

namespace WebCore {

template<typename PropertyType>
class SVGPropertyTearOff;

template<typename PropertyType>
class SVGAnimatedListPropertyTearOff : public SVGAnimatedProperty {
public:
    typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
    typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
    typedef Vector<RefPtr<ListItemTearOff> > ListWrapperCache;
    typedef SVGListProperty<PropertyType> ListProperty;
    typedef SVGListPropertyTearOff<PropertyType> ListPropertyTearOff;
    typedef PropertyType ContentType;

    virtual ListProperty* baseVal()
    {
        if (!m_baseVal)
            m_baseVal = ListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers);
        return static_cast<ListProperty*>(m_baseVal.get());
    }

    virtual ListProperty* animVal()
    {
        if (!m_animVal)
            m_animVal = ListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers);
        return static_cast<ListProperty*>(m_animVal.get());
    }

    virtual bool isAnimatedListTearOff() const { return true; }

    int findItem(SVGProperty* property) const
    {
        // This should ever be called for our baseVal, as animVal can't modify the list.
        // It's safe to cast to ListPropertyTearOff here as all classes inheriting from us supply their own removeItemFromList() method.
        typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff;
        return static_cast<ListPropertyTearOff*>(m_baseVal.get())->findItem(static_cast<ListItemTearOff*>(property));
    }

    void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers)
    {
        // This should ever be called for our baseVal, as animVal can't modify the list.
        // It's safe to cast to ListPropertyTearOff here as all classes inheriting from us supply their own removeItemFromList() method.
        static_cast<ListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers);
    }

    void detachListWrappers(unsigned newListSize)
    {
        ListProperty::detachListWrappersAndResize(&m_wrappers, newListSize);
    }

    PropertyType& currentAnimatedValue()
    {
        ASSERT(m_isAnimating);
        ASSERT(m_animVal);
        return static_cast<ListProperty*>(m_animVal.get())->values();
    }

    const PropertyType& currentBaseValue() const
    {
        return m_values;
    }

    void animationStarted(PropertyType* newAnimVal, bool shouldOwnValues = false)
    {
        ASSERT(!m_isAnimating);
        ASSERT(newAnimVal);
        ASSERT(m_values.size() == m_wrappers.size());
        ASSERT(m_animatedWrappers.isEmpty());

        // Switch to new passed in value type & new wrappers list. The new wrappers list must be created for the new value.
        if (!newAnimVal->isEmpty())
            m_animatedWrappers.fill(0, newAnimVal->size());

        ListProperty* animVal = static_cast<ListProperty*>(this->animVal());
        animVal->setValuesAndWrappers(newAnimVal, &m_animatedWrappers, shouldOwnValues);
        ASSERT(animVal->values().size() == animVal->wrappers().size());
        ASSERT(animVal->wrappers().size() == m_animatedWrappers.size());
        m_isAnimating = true;
    }

    void animationEnded()
    {
        ASSERT(m_isAnimating);
        ASSERT(m_animVal);
        ASSERT(contextElement());

        ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get());
        if (animVal->wrappers().size()) {
            ASSERT(m_values.size() == m_wrappers.size());
            ASSERT(animVal->values().size() == animVal->wrappers().size());
            ASSERT(animVal->wrappers().size() == m_animatedWrappers.size());

            animVal->setValuesAndWrappers(&m_values, &m_wrappers, false);
            ASSERT(animVal->values().size() == animVal->wrappers().size());
            ASSERT(animVal->wrappers().size() == m_wrappers.size());
        }
        m_animatedWrappers.clear();
        m_isAnimating = false;
    }

    void synchronizeWrappersIfNeeded()
    {
        // Eventually the wrapper list needs synchronization because any SVGAnimateLengthList::calculateAnimatedValue() call may
        // mutate the length of our values() list, and thus the wrapper() cache needs synchronization, to have the same size.
        // Also existing wrappers which point directly at elements in the existing SVGLengthList have to be detached (so a copy
        // of them is created, so existing animVal variables in JS are kept-alive). If we'd detach them later the underlying
        // SVGLengthList was already mutated, and our list item wrapper tear offs would point nowhere. Assertions would fire.
        ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get());
        animVal->detachListWrappers(animVal->values().size());

        ASSERT(animVal->values().size() == animVal->wrappers().size());
        ASSERT(animVal->wrappers().size() == m_animatedWrappers.size());
    }

    void animValWillChange()
    {
        ASSERT(m_isAnimating);
        ASSERT(m_animVal);
        ASSERT(m_values.size() == m_wrappers.size());
        synchronizeWrappersIfNeeded();
    }

    void animValDidChange()
    {
        ASSERT(m_isAnimating);
        ASSERT(m_animVal);
        ASSERT(m_values.size() == m_wrappers.size());
        synchronizeWrappersIfNeeded();
    }

    virtual void detachWrappers() OVERRIDE
    {
        if (m_animVal) {
            ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get());
            animVal->detachListWrappers(0);
        }
    }

    static PassRefPtr<SVGAnimatedListPropertyTearOff<PropertyType> > create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& values)
    {
        ASSERT(contextElement);
        return adoptRef(new SVGAnimatedListPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, values));
    }

protected:
    SVGAnimatedListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& values)
        : SVGAnimatedProperty(contextElement, attributeName, animatedPropertyType)
        , m_values(values)
    {
        if (!values.isEmpty())
            m_wrappers.fill(0, values.size());
    }

    ~SVGAnimatedListPropertyTearOff()
    {
        if (m_baseVal)
            static_cast<ListPropertyTearOff*>(m_baseVal.get())->clearAnimatedProperty();
        if (m_animVal)
            static_cast<ListPropertyTearOff*>(m_animVal.get())->clearAnimatedProperty();
    }

    PropertyType& m_values;

    ListWrapperCache m_wrappers;
    ListWrapperCache m_animatedWrappers;

    RefPtr<SVGProperty> m_baseVal;
    RefPtr<SVGProperty> m_animVal;
};

}

#endif // SVGAnimatedListPropertyTearOff_h
