/*
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 * 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 "SVGPathByteStream.h"
#include "SVGPathSeg.h"
#include "SVGPropertyList.h"

namespace WebCore {

class SVGPathSegList final : public SVGPropertyList<SVGPathSeg> {
    friend class SVGAnimatedPathSegListAnimator;
    friend class SVGPathSegListBuilder;
    friend class SVGPathSegListSource;

    using Base = SVGPropertyList<SVGPathSeg>;
    using Base::Base;

public:
    static Ref<SVGPathSegList> create(SVGPropertyOwner* owner, SVGPropertyAccess access)
    {
        return adoptRef(*new SVGPathSegList(owner, access));
    }

    static Ref<SVGPathSegList> create(const SVGPathSegList& other, SVGPropertyAccess access)
    {
        return adoptRef(*new SVGPathSegList(other, access));
    }

    static Ref<SVGPathSegList> create(Ref<SVGPathSeg>&& newItem)
    {
        return adoptRef(*new SVGPathSegList(WTFMove(newItem)));
    }

    SVGPathSegList& operator=(const SVGPathSegList& other)
    {
        pathByteStreamWillChange();
        m_pathByteStream = other.pathByteStream();
        return *this;
    }

    unsigned numberOfItems() const
    {
        const_cast<SVGPathSegList*>(this)->ensureItems();
        return Base::numberOfItems();
    }

    ExceptionOr<void> clear()
    {
        itemsWillChange();
        return Base::clear();
    }

    ExceptionOr<Ref<SVGPathSeg>> getItem(unsigned index)
    {
        ensureItems();
        return Base::getItem(index);
    }

    ExceptionOr<Ref<SVGPathSeg>> initialize(Ref<SVGPathSeg>&& newItem)
    {
        itemsWillChange();
        return Base::initialize(WTFMove(newItem));
    }

    ExceptionOr<Ref<SVGPathSeg>> insertItemBefore(Ref<SVGPathSeg>&& newItem, unsigned index)
    {
        ensureItems();
        itemsWillChange();
        return Base::insertItemBefore(WTFMove(newItem), index);
    }

    ExceptionOr<Ref<SVGPathSeg>> replaceItem(Ref<SVGPathSeg>&& newItem, unsigned index)
    {
        ensureItems();
        itemsWillChange();
        return Base::replaceItem(WTFMove(newItem), index);
    }

    ExceptionOr<Ref<SVGPathSeg>> removeItem(unsigned index)
    {
        ensureItems();
        itemsWillChange();
        return Base::removeItem(index);
    }

    ExceptionOr<Ref<SVGPathSeg>> appendItem(Ref<SVGPathSeg>&& newItem)
    {
        ensureItems();
        appendPathSegToPathByteStream(newItem);
        clearPath();
        return Base::appendItem(WTFMove(newItem));
    }

    const SVGPathByteStream& pathByteStream() const { return const_cast<SVGPathSegList*>(this)->pathByteStream(); }
    SVGPathByteStream& pathByteStream()
    {
        ensurePathByteStream();
        return m_pathByteStream;
    }

    bool parse(const String& value)
    {
        pathByteStreamWillChange();
        return buildSVGPathByteStreamFromString(value, m_pathByteStream, UnalteredParsing);
    }

    Path path() const
    {
        if (!m_path)
            m_path = buildPathFromByteStream(pathByteStream());
        return *m_path;
    }

    size_t approximateMemoryCost() const
    {
        // This is an approximation for path memory cost since the path is parsed on demand.
        size_t pathMemoryCost = (m_pathByteStream.size() / 10) * sizeof(FloatPoint);
        // We need to account for the memory which is allocated by the m_path.
        return m_path ? pathMemoryCost + sizeof(*m_path) : pathMemoryCost;
    }

    String valueAsString() const override
    {
        String value;
        buildStringFromByteStream(pathByteStream(), value, UnalteredParsing);
        return value;
    }

private:
    SVGPathSegList(const SVGPathSegList& other, SVGPropertyAccess access)
        : Base(other.owner(), access)
        , m_pathByteStream(other.pathByteStream())
    {
    }

    // Used by appendPathSegToPathByteStream() to create a temporary SVGPathSegList with one item.
    SVGPathSegList(Ref<SVGPathSeg>&& newItem)
    {
        append(WTFMove(newItem));
    }

    // Called when changing an item in the list.
    void commitPropertyChange(SVGProperty* property) override
    {
        itemsWillChange();
        Base::commitPropertyChange(property);
    }

    void ensureItems()
    {
        if (!m_items.isEmpty() || m_pathByteStream.isEmpty())
            return;
        buildSVGPathSegListFromByteStream(m_pathByteStream, *this, UnalteredParsing);
    }

    void ensurePathByteStream()
    {
        if (!m_pathByteStream.isEmpty() || m_items.isEmpty())
            return;
        buildSVGPathByteStreamFromSVGPathSegList(*this, m_pathByteStream, UnalteredParsing);
    }

    // Optimize appending an SVGPathSeg to the list. Instead of creating the whole
    // byte stream, a temporary byte stream will be creating just for the new item
    // and this temporary byte stream will be appended to m_pathByteStream.
    void appendPathSegToPathByteStream(const Ref<SVGPathSeg>& item)
    {
        if (m_pathByteStream.isEmpty())
            return;

        Ref<SVGPathSegList> pathSegList = SVGPathSegList::create(item.copyRef());
        SVGPathByteStream pathSegStream;

        if (!buildSVGPathByteStreamFromSVGPathSegList(pathSegList, pathSegStream, UnalteredParsing, false))
            return;

        m_pathByteStream.append(pathSegStream);
    }

    void clearPathByteStream() { m_pathByteStream.clear(); }
    void clearPath() { m_path = WTF::nullopt; }

    void pathByteStreamWillChange()
    {
        clearItems();
        clearPath();
    }

    void itemsWillChange()
    {
        clearPathByteStream();
        clearPath();
    }

    SVGPathByteStream m_pathByteStream;
    mutable Optional<Path> m_path;
};

}
