/*
 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 * Copyright (C) 2018-2019 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 "Path.h"
#include "SVGExternalResourcesRequired.h"
#include "SVGGeometryElement.h"
#include "SVGNames.h"
#include "SVGPathByteStream.h"
#include "SVGPathSegImpl.h"

namespace WebCore {

class SVGPathSegList;
class SVGPoint;

class SVGPathElement final : public SVGGeometryElement, public SVGExternalResourcesRequired {
    WTF_MAKE_ISO_ALLOCATED(SVGPathElement);
public:
    static Ref<SVGPathElement> create(const QualifiedName&, Document&);
    
    static Ref<SVGPathSegClosePath> createSVGPathSegClosePath() { return SVGPathSegClosePath::create(); }
    static Ref<SVGPathSegMovetoAbs> createSVGPathSegMovetoAbs(float x, float y) { return SVGPathSegMovetoAbs::create(x, y); }
    static Ref<SVGPathSegMovetoRel> createSVGPathSegMovetoRel(float x, float y) { return SVGPathSegMovetoRel::create(x, y); }
    static Ref<SVGPathSegLinetoAbs> createSVGPathSegLinetoAbs(float x, float y) { return SVGPathSegLinetoAbs::create(x, y); }
    static Ref<SVGPathSegLinetoRel> createSVGPathSegLinetoRel(float x, float y) { return SVGPathSegLinetoRel::create(x, y); }
    static Ref<SVGPathSegCurvetoCubicAbs> createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
    {
        return SVGPathSegCurvetoCubicAbs::create(x, y, x1, y1, x2, y2);
    }
    static Ref<SVGPathSegCurvetoCubicRel> createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
    {
        return SVGPathSegCurvetoCubicRel::create(x, y, x1, y1, x2, y2);
    }
    static Ref<SVGPathSegCurvetoQuadraticAbs> createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
    {
        return SVGPathSegCurvetoQuadraticAbs::create(x, y, x1, y1);
    }
    static Ref<SVGPathSegCurvetoQuadraticRel> createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
    {
        return SVGPathSegCurvetoQuadraticRel::create(x, y, x1, y1);
    }
    static Ref<SVGPathSegArcAbs> createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
    {
        return SVGPathSegArcAbs::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
    }
    static Ref<SVGPathSegArcRel> createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
    {
        return SVGPathSegArcRel::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
    }
    static Ref<SVGPathSegLinetoHorizontalAbs> createSVGPathSegLinetoHorizontalAbs(float x) { return SVGPathSegLinetoHorizontalAbs::create(x); }
    static Ref<SVGPathSegLinetoHorizontalRel> createSVGPathSegLinetoHorizontalRel(float x) { return SVGPathSegLinetoHorizontalRel::create(x); }
    static Ref<SVGPathSegLinetoVerticalAbs> createSVGPathSegLinetoVerticalAbs(float y) { return SVGPathSegLinetoVerticalAbs::create(y); }
    static Ref<SVGPathSegLinetoVerticalRel> createSVGPathSegLinetoVerticalRel(float y) { return SVGPathSegLinetoVerticalRel::create(y); }
    static Ref<SVGPathSegCurvetoCubicSmoothAbs> createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
    {
        return SVGPathSegCurvetoCubicSmoothAbs::create(x, y, x2, y2);
    }
    static Ref<SVGPathSegCurvetoCubicSmoothRel> createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
    {
        return SVGPathSegCurvetoCubicSmoothRel::create(x, y, x2, y2);
    }
    static Ref<SVGPathSegCurvetoQuadraticSmoothAbs> createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
    {
        return SVGPathSegCurvetoQuadraticSmoothAbs::create(x, y);
    }
    static Ref<SVGPathSegCurvetoQuadraticSmoothRel> createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
    {
        return SVGPathSegCurvetoQuadraticSmoothRel::create(x, y);
    }

    float getTotalLength() const final;
    Ref<SVGPoint> getPointAtLength(float distance) const final;
    unsigned getPathSegAtLength(float distance) const;

    FloatRect getBBox(StyleUpdateStrategy = AllowStyleUpdate) final;

    Ref<SVGPathSegList>& pathSegList() { return m_pathSegList->baseVal(); }
    RefPtr<SVGPathSegList>& animatedPathSegList() { return m_pathSegList->animVal(); }

    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists!
    RefPtr<SVGPathSegList> normalizedPathSegList() { return nullptr; }
    RefPtr<SVGPathSegList> animatedNormalizedPathSegList() { return nullptr; }

    const SVGPathByteStream& pathByteStream() const { return m_pathSegList->currentPathByteStream(); }
    Path path() const { return m_pathSegList->currentPath(); }
    size_t approximateMemoryCost() const final { return m_pathSegList->approximateMemoryCost(); }

private:
    SVGPathElement(const QualifiedName&, Document&);

    using PropertyRegistry = SVGPropertyOwnerRegistry<SVGPathElement, SVGGeometryElement, SVGExternalResourcesRequired>;
    const SVGPropertyRegistry& propertyRegistry() const final { return m_propertyRegistry; }
    
    void parseAttribute(const QualifiedName&, const AtomString&) final;
    void svgAttributeChanged(const QualifiedName&) final;

    bool isValid() const final { return SVGTests::isValid(); }
    bool supportsMarkers() const final { return true; }

    RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;

    Node::InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final;
    void removedFromAncestor(RemovalType, ContainerNode&) final;

    void invalidateMPathDependencies();

private:
    PropertyRegistry m_propertyRegistry { *this };
    Ref<SVGAnimatedPathSegList> m_pathSegList { SVGAnimatedPathSegList::create(this) };
};

} // namespace WebCore
