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

#pragma once

#include "SVGAnimatedProperty.h"
#include "SVGPropertyTearOff.h"

namespace WebCore {

template<typename T>
class SVGAnimatedPropertyTearOff final : public SVGAnimatedProperty {
public:
    using PropertyTearOff = T;
    using PropertyType = typename PropertyTearOff::PropertyType;
    using ContentType = PropertyType;

    static Ref<SVGAnimatedPropertyTearOff<PropertyTearOff>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property)
    {
        ASSERT(contextElement);
        return adoptRef(*new SVGAnimatedPropertyTearOff<PropertyTearOff>(contextElement, attributeName, animatedPropertyType, property));
    }

    Ref<PropertyTearOff> baseVal()
    {
        if (m_baseVal)
            return *static_cast<PropertyTearOff*>(m_baseVal.get());

        auto property = PropertyTearOff::create(*this, BaseValRole, m_property);
        m_baseVal = property->createWeakPtr();
        return property;
    }

    Ref<PropertyTearOff> animVal()
    {
        if (m_animVal)
            return *static_cast<PropertyTearOff*>(m_animVal.get());

        auto property = PropertyTearOff::create(*this, AnimValRole, m_property);
        m_animVal = property->createWeakPtr();
        return property;
    }

    bool isAnimating() const final { return m_animatedProperty; }

    PropertyType& currentAnimatedValue()
    {
        ASSERT(isAnimating());
        return m_animatedProperty->propertyReference();
    }

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

    void animationStarted(PropertyType* newAnimVal)
    {
        ASSERT(!isAnimating());
        ASSERT(newAnimVal);
        m_animatedProperty = animVal();
        m_animatedProperty->setValue(*newAnimVal);
    }

    void animationEnded()
    {
        ASSERT(isAnimating());
        m_animatedProperty->setValue(m_property);
        m_animatedProperty = nullptr;
    }

    void animValWillChange()
    {
        // no-op for non list types.
        ASSERT(isAnimating());
    }

    void animValDidChange()
    {
        // no-op for non list types.
        ASSERT(isAnimating());
    }

    void synchronizeWrappersIfNeeded()
    {
        // no-op
    }

private:
    SVGAnimatedPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property)
        : SVGAnimatedProperty(contextElement, attributeName, animatedPropertyType)
        , m_property(property)
    {
    }

    PropertyType& m_property;
    WeakPtr<SVGPropertyTearOff<PropertyType>> m_baseVal;
    WeakPtr<SVGPropertyTearOff<PropertyType>> m_animVal;

    RefPtr<PropertyTearOff> m_animatedProperty;
};

}
