/*
 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 * Copyright (C) 2015-2021 Apple Inc. All right 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.
 */

#include "config.h"
#include "SVGTests.h"

#include "DOMImplementation.h"
#include "HTMLNames.h"
#include "SVGElement.h"
#include "SVGNames.h"
#include "SVGStringList.h"
#include <wtf/Language.h>
#include <wtf/SortedArrayMap.h>

#if ENABLE(MATHML)
#include "MathMLNames.h"
#endif

namespace WebCore {

constexpr ComparableLettersLiteral supportedSVGFeatureArray[] = {
    "http://www.w3.org/tr/svg11/feature#animation",
    "http://www.w3.org/tr/svg11/feature#basegraphicsattribute",
    "http://www.w3.org/tr/svg11/feature#basicclip",
    "http://www.w3.org/tr/svg11/feature#basicfilter",
    "http://www.w3.org/tr/svg11/feature#basicfont",
    "http://www.w3.org/tr/svg11/feature#basicpaintattribute",
    "http://www.w3.org/tr/svg11/feature#basicstructure",
    "http://www.w3.org/tr/svg11/feature#basictext",
    "http://www.w3.org/tr/svg11/feature#clip",
    "http://www.w3.org/tr/svg11/feature#conditionalprocessing",
    "http://www.w3.org/tr/svg11/feature#containerattribute",
    "http://www.w3.org/tr/svg11/feature#coreattribute",
    "http://www.w3.org/tr/svg11/feature#cursor",
    "http://www.w3.org/tr/svg11/feature#documenteventsattribute",
    "http://www.w3.org/tr/svg11/feature#extensibility",
    "http://www.w3.org/tr/svg11/feature#externalresourcesrequired",
    "http://www.w3.org/tr/svg11/feature#filter",
    "http://www.w3.org/tr/svg11/feature#font",
    "http://www.w3.org/tr/svg11/feature#gradient",
    "http://www.w3.org/tr/svg11/feature#graphicaleventsattribute",
    "http://www.w3.org/tr/svg11/feature#graphicsattribute",
    "http://www.w3.org/tr/svg11/feature#hyperlinking",
    "http://www.w3.org/tr/svg11/feature#image",
    "http://www.w3.org/tr/svg11/feature#marker",
    "http://www.w3.org/tr/svg11/feature#mask",
    "http://www.w3.org/tr/svg11/feature#opacityattribute",
    "http://www.w3.org/tr/svg11/feature#paintattribute",
    "http://www.w3.org/tr/svg11/feature#pattern",
    "http://www.w3.org/tr/svg11/feature#script",
    "http://www.w3.org/tr/svg11/feature#shape",
    "http://www.w3.org/tr/svg11/feature#structure",
    "http://www.w3.org/tr/svg11/feature#style",
    "http://www.w3.org/tr/svg11/feature#svg",
    "http://www.w3.org/tr/svg11/feature#svg-animation",
    "http://www.w3.org/tr/svg11/feature#svg-static",
    "http://www.w3.org/tr/svg11/feature#svgdom",
    "http://www.w3.org/tr/svg11/feature#svgdom-animation",
    "http://www.w3.org/tr/svg11/feature#svgdom-static",
    "http://www.w3.org/tr/svg11/feature#text",
    "http://www.w3.org/tr/svg11/feature#view",
    "http://www.w3.org/tr/svg11/feature#viewportattribute",
    "http://www.w3.org/tr/svg11/feature#xlinkattribute",
    "org.w3c.dom",
    "org.w3c.dom.svg",
    "org.w3c.dom.svg.static",
    "org.w3c.svg",
    "org.w3c.svg.static",
};

constexpr SortedArraySet supportedSVGFeatureSet { supportedSVGFeatureArray };

SVGTests::SVGTests(SVGElement* contextElement)
    : m_contextElement(*contextElement)
    , m_requiredFeatures(SVGStringList::create(contextElement))
    , m_requiredExtensions(SVGStringList::create(contextElement))
    , m_systemLanguage(SVGStringList::create(contextElement))
{
    static std::once_flag onceFlag;
    std::call_once(onceFlag, [] {
        PropertyRegistry::registerProperty<SVGNames::requiredFeaturesAttr, &SVGTests::m_requiredFeatures>();
        PropertyRegistry::registerProperty<SVGNames::requiredExtensionsAttr, &SVGTests::m_requiredExtensions>();
        PropertyRegistry::registerProperty<SVGNames::systemLanguageAttr, &SVGTests::m_systemLanguage>();
    });
}

bool SVGTests::hasExtension(const String& extension)
{
    // We recognize XHTML and MathML, as implemented in Gecko and suggested in the SVG Tiny recommendation (http://www.w3.org/TR/SVG11/struct.html#RequiredExtensionsAttribute).
#if ENABLE(MATHML)
    if (extension == MathMLNames::mathmlNamespaceURI)
        return true;
#endif
    return extension == HTMLNames::xhtmlNamespaceURI;
}

bool SVGTests::isValid() const
{
    for (auto& feature : m_requiredFeatures->items()) {
        if (feature.isEmpty() || !supportedSVGFeatureSet.contains(feature))
            return false;
    }
    for (auto& language : m_systemLanguage->items()) {
        if (language != defaultLanguage().substring(0, 2))
            return false;
    }
    for (auto& extension : m_requiredExtensions->items()) {
        if (!hasExtension(extension))
            return false;
    }
    return true;
}

void SVGTests::parseAttribute(const QualifiedName& attributeName, const AtomString& value)
{
    if (attributeName == SVGNames::requiredFeaturesAttr)
        m_requiredFeatures->reset(value);
    if (attributeName == SVGNames::requiredExtensionsAttr)
        m_requiredExtensions->reset(value);
    if (attributeName == SVGNames::systemLanguageAttr)
        m_systemLanguage->reset(value);
}

void SVGTests::svgAttributeChanged(const QualifiedName& attrName)
{
    if (!PropertyRegistry::isKnownAttribute(attrName))
        return;

    if (!m_contextElement.isConnected())
        return;
    m_contextElement.invalidateStyleAndRenderersForSubtree();
}

void SVGTests::addSupportedAttributes(MemoryCompactLookupOnlyRobinHoodHashSet<QualifiedName>& supportedAttributes)
{
    supportedAttributes.add(SVGNames::requiredFeaturesAttr);
    supportedAttributes.add(SVGNames::requiredExtensionsAttr);
    supportedAttributes.add(SVGNames::systemLanguageAttr);
}

bool SVGTests::hasFeatureForLegacyBindings(const String& feature, const String& version)
{
    // FIXME: This function is here only to be exposed in the Objective-C and GObject bindings for both Node and DOMImplementation.
    // It's likely that we can just remove this and instead have the bindings return true unconditionally.
    // This is what the DOMImplementation function now does in JavaScript as is now suggested in the DOM specification.
    // The behavior implemented below is quirky, but preserves what WebKit has done for at least the last few years.

    bool hasSVG10FeaturePrefix = startsWithLettersIgnoringASCIICase(feature, "org.w3c.dom.svg") || startsWithLettersIgnoringASCIICase(feature, "org.w3c.svg");
    bool hasSVG11FeaturePrefix = startsWithLettersIgnoringASCIICase(feature, "http://www.w3.org/tr/svg");

    // We don't even try to handle feature names that don't look like the SVG ones, so just return true for all of those.
    if (!(hasSVG10FeaturePrefix || hasSVG11FeaturePrefix))
        return true;

    // If the version number matches the style of the feature name, then use the set to see if the feature is supported.
    if (version.isEmpty() || (hasSVG10FeaturePrefix && version == "1.0") || (hasSVG11FeaturePrefix && version == "1.1"))
        return supportedSVGFeatureSet.contains(feature);

    return false;
}

}
