/*
 * Copyright (C) 2016 Igalia, S.L.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "AccessibilitySVGElement.h"

#include "AXObjectCache.h"
#include "ElementIterator.h"
#include "HTMLNames.h"
#include "RenderIterator.h"
#include "RenderText.h"
#include "SVGAElement.h"
#include "SVGDescElement.h"
#include "SVGGElement.h"
#include "SVGTitleElement.h"
#include "SVGUseElement.h"
#include "XLinkNames.h"
#include <wtf/Language.h>

namespace WebCore {

AccessibilitySVGElement::AccessibilitySVGElement(RenderObject* renderer)
    : AccessibilityRenderObject(renderer)
{
}

AccessibilitySVGElement::~AccessibilitySVGElement() = default;

Ref<AccessibilitySVGElement> AccessibilitySVGElement::create(RenderObject* renderer)
{
    return adoptRef(*new AccessibilitySVGElement(renderer));
}

AccessibilityObject* AccessibilitySVGElement::targetForUseElement() const
{
    if (!is<SVGUseElement>(element()))
        return nullptr;

    SVGUseElement& use = downcast<SVGUseElement>(*element());
    String href = use.href();
    if (href.isEmpty())
        href = getAttribute(HTMLNames::hrefAttr);

    Element* target = SVGURIReference::targetElementFromIRIString(href, use.document());
    if (target)
        return axObjectCache()->getOrCreate(target);

    return nullptr;
}

template <typename ChildrenType>
Element* AccessibilitySVGElement::childElementWithMatchingLanguage(ChildrenType& children) const
{
    String languageCode = language();
    if (languageCode.isEmpty())
        languageCode = defaultLanguage();

    // The best match for a group of child SVG2 'title' or 'desc' elements may be the one
    // which lacks a 'lang' attribute value. However, indexOfBestMatchingLanguageInList()
    // currently bases its decision on non-empty strings. Furthermore, we cannot count on
    // that child element having a given position. So we'll look for such an element while
    // building the language list and save it as our fallback.

    Element* fallback = nullptr;
    Vector<String> childLanguageCodes;
    Vector<Element*> elements;
    for (auto& child : children) {
        auto& lang = child.attributeWithoutSynchronization(SVGNames::langAttr);
        childLanguageCodes.append(lang);
        elements.append(&child);

        // The current draft of the SVG2 spec states if there are multiple equally-valid
        // matches, the first match should be used.
        if (lang.isEmpty() && !fallback)
            fallback = &child;
    }

    bool exactMatch;
    size_t index = indexOfBestMatchingLanguageInList(languageCode, childLanguageCodes, exactMatch);
    if (index < childLanguageCodes.size())
        return elements[index];

    return fallback;
}

void AccessibilitySVGElement::accessibilityText(Vector<AccessibilityText>& textOrder)
{
    String description = accessibilityDescription();
    if (!description.isEmpty())
        textOrder.append(AccessibilityText(description, AccessibilityTextSource::Alternative));

    String helptext = helpText();
    if (!helptext.isEmpty())
        textOrder.append(AccessibilityText(helptext, AccessibilityTextSource::Help));
}

String AccessibilitySVGElement::accessibilityDescription() const
{
    // According to the SVG Accessibility API Mappings spec, the order of priority is:
    // 1. aria-labelledby
    // 2. aria-label
    // 3. a direct child title element (selected according to language)
    // 4. xlink:title attribute
    // 5. for a use element, the accessible name calculated for the re-used content
    // 6. for text container elements, the text content

    String ariaDescription = ariaAccessibilityDescription();
    if (!ariaDescription.isEmpty())
        return ariaDescription;

    auto titleElements = childrenOfType<SVGTitleElement>(*element());
    if (auto titleChild = childElementWithMatchingLanguage(titleElements))
        return titleChild->textContent();

    if (is<SVGAElement>(element())) {
        auto& xlinkTitle = element()->attributeWithoutSynchronization(XLinkNames::titleAttr);
        if (!xlinkTitle.isEmpty())
            return xlinkTitle;
    }

    if (m_renderer->isSVGText()) {
        AccessibilityTextUnderElementMode mode;
        String text = textUnderElement(mode);
        if (!text.isEmpty())
            return text;
    }

    if (is<SVGUseElement>(element())) {
        if (AccessibilityObject* target = targetForUseElement())
            return target->accessibilityDescription();
    }

    // FIXME: This is here to not break the svg-image.html test. But 'alt' is not
    // listed as a supported attribute of the 'image' element in the SVG spec:
    // https://www.w3.org/TR/SVG/struct.html#ImageElement
    if (m_renderer->isSVGImage()) {
        const AtomicString& alt = getAttribute(HTMLNames::altAttr);
        if (!alt.isNull())
            return alt;
    }

    return String();
}

String AccessibilitySVGElement::helpText() const
{
    // According to the SVG Accessibility API Mappings spec, the order of priority is:
    // 1. aria-describedby
    // 2. a direct child desc element
    // 3. for a use element, the accessible description calculated for the re-used content
    // 4. for text container elements, the text content, if not used for the name
    // 5. a direct child title element that provides a tooltip, if not used for the name

    String describedBy = ariaDescribedByAttribute();
    if (!describedBy.isEmpty())
        return describedBy;

    auto descriptionElements = childrenOfType<SVGDescElement>(*element());
    if (auto descriptionChild = childElementWithMatchingLanguage(descriptionElements))
        return descriptionChild->textContent();

    if (is<SVGUseElement>(element())) {
        AccessibilityObject* target = targetForUseElement();
        if (target)
            return target->helpText();
    }

    String description = accessibilityDescription();

    if (m_renderer->isSVGText()) {
        AccessibilityTextUnderElementMode mode;
        String text = textUnderElement(mode);
        if (!text.isEmpty() && text != description)
            return text;
    }

    auto titleElements = childrenOfType<SVGTitleElement>(*element());
    if (auto titleChild = childElementWithMatchingLanguage(titleElements)) {
        if (titleChild->textContent() != description)
            return titleChild->textContent();
    }

    return String();
}

bool AccessibilitySVGElement::computeAccessibilityIsIgnored() const
{
    // According to the SVG Accessibility API Mappings spec, items should be excluded if:
    // * They would be excluded according to the Core Accessibility API Mappings.
    // * They are neither perceivable nor interactive.
    // * Their first mappable role is presentational, unless they have a global ARIA
    //   attribute (covered by Core AAM) or at least one 'title' or 'desc' child element.
    // * They have an ancestor with Children Presentational: True (covered by Core AAM)

    AccessibilityObjectInclusion decision = defaultObjectInclusion();
    if (decision == AccessibilityObjectInclusion::IgnoreObject)
        return true;

    if (m_renderer->isSVGHiddenContainer())
        return true;

    // The SVG AAM states objects with at least one 'title' or 'desc' element MUST be included.
    // At this time, the presence of a matching 'lang' attribute is not mentioned in the spec.
    for (const auto& child : childrenOfType<SVGElement>(*element())) {
        if ((is<SVGTitleElement>(child) || is<SVGDescElement>(child)))
            return false;
    }

    if (roleValue() == AccessibilityRole::Presentational || inheritsPresentationalRole())
        return true;

    if (ariaRoleAttribute() != AccessibilityRole::Unknown)
        return false;

    // The SVG AAM states text elements should also be included, if they have content.
    if (m_renderer->isSVGText() || m_renderer->isSVGTextPath()) {
        for (auto& child : childrenOfType<RenderText>(downcast<RenderElement>(*m_renderer))) {
            if (!child.isAllCollapsibleWhitespace())
                return false;
        }
    }

    // SVG shapes should not be included unless there's a concrete reason for inclusion.
    // https://rawgit.com/w3c/aria/master/svg-aam/svg-aam.html#exclude_elements
    if (m_renderer->isSVGShape())
        return !(hasAttributesRequiredForInclusion() || canSetFocusAttribute() || element()->hasEventListeners());

    return AccessibilityRenderObject::computeAccessibilityIsIgnored();
}

bool AccessibilitySVGElement::inheritsPresentationalRole() const
{
    if (canSetFocusAttribute())
        return false;

    AccessibilityRole role = roleValue();
    if (role != AccessibilityRole::SVGTextPath && role != AccessibilityRole::SVGTSpan)
        return false;

    for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
        if (is<AccessibilityRenderObject>(*parent) && parent->element()->hasTagName(SVGNames::textTag))
            return parent->roleValue() == AccessibilityRole::Presentational;
    }

    return false;
}

AccessibilityRole AccessibilitySVGElement::determineAriaRoleAttribute() const
{
    AccessibilityRole role = AccessibilityRenderObject::determineAriaRoleAttribute();
    if (role != AccessibilityRole::Presentational)
        return role;

    // The presence of a 'title' or 'desc' child element trumps PresentationalRole.
    // https://lists.w3.org/Archives/Public/public-svg-a11y/2016Apr/0016.html
    // At this time, the presence of a matching 'lang' attribute is not mentioned.
    for (const auto& child : childrenOfType<SVGElement>(*element())) {
        if ((is<SVGTitleElement>(child) || is<SVGDescElement>(child)))
            return AccessibilityRole::Unknown;
    }

    return role;
}

AccessibilityRole AccessibilitySVGElement::determineAccessibilityRole()
{
    if ((m_ariaRole = determineAriaRoleAttribute()) != AccessibilityRole::Unknown)
        return m_ariaRole;

    Element* svgElement = element();

    if (m_renderer->isSVGShape() || m_renderer->isSVGPath() || m_renderer->isSVGImage() || is<SVGUseElement>(svgElement))
        return AccessibilityRole::Image;
    if (m_renderer->isSVGForeignObject() || is<SVGGElement>(svgElement))
        return AccessibilityRole::Group;
    if (m_renderer->isSVGText())
        return AccessibilityRole::SVGText;
    if (m_renderer->isSVGTextPath())
        return AccessibilityRole::SVGTextPath;
    if (m_renderer->isSVGTSpan())
        return AccessibilityRole::SVGTSpan;
    if (is<SVGAElement>(svgElement))
        return AccessibilityRole::WebCoreLink;

    return AccessibilityRenderObject::determineAccessibilityRole();
}

} // namespace WebCore
