/*
 * 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"

#if ENABLE(MATHML)
#include "AccessibilityMathMLElement.h"

#include "AXObjectCache.h"
#include "MathMLNames.h"

namespace WebCore {

AccessibilityMathMLElement::AccessibilityMathMLElement(RenderObject* renderer, bool isAnonymousOperator)
    : AccessibilityRenderObject(renderer)
    , m_isAnonymousOperator(isAnonymousOperator)
{
}

AccessibilityMathMLElement::~AccessibilityMathMLElement() = default;

Ref<AccessibilityMathMLElement> AccessibilityMathMLElement::create(RenderObject* renderer, bool isAnonymousOperator)
{
    return adoptRef(*new AccessibilityMathMLElement(renderer, isAnonymousOperator));
}

AccessibilityRole AccessibilityMathMLElement::determineAccessibilityRole()
{
    if (!m_renderer)
        return AccessibilityRole::Unknown;

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

    Node* node = m_renderer->node();
    if (node && node->hasTagName(MathMLNames::mathTag))
        return AccessibilityRole::DocumentMath;

    // It's not clear which role a platform should choose for a math element.
    // Declaring a math element role should give flexibility to platforms to choose.
    return AccessibilityRole::MathElement;
}

String AccessibilityMathMLElement::textUnderElement(AccessibilityTextUnderElementMode mode) const
{
    if (m_isAnonymousOperator) {
        UChar operatorChar = downcast<RenderMathMLOperator>(*m_renderer).textContent();
        return operatorChar ? String(&operatorChar, 1) : String();
    }

    return AccessibilityRenderObject::textUnderElement(mode);
}

String AccessibilityMathMLElement::stringValue() const
{
    if (m_isAnonymousOperator)
        return textUnderElement();

    return AccessibilityRenderObject::stringValue();
}

bool AccessibilityMathMLElement::isIgnoredElementWithinMathTree() const
{
    if (m_isAnonymousOperator)
        return false;

    // Only math elements that we explicitly recognize should be included
    // We don't want things like <mstyle> to appear in the tree.
    if (isMathFraction() || isMathFenced() || isMathSubscriptSuperscript() || isMathRow()
        || isMathUnderOver() || isMathRoot() || isMathText() || isMathNumber()
        || isMathOperator() || isMathFenceOperator() || isMathSeparatorOperator()
        || isMathIdentifier() || isMathTable() || isMathTableRow() || isMathTableCell() || isMathMultiscript())
        return false;

    return true;
}

bool AccessibilityMathMLElement::isMathFraction() const
{
    return m_renderer && m_renderer->isRenderMathMLFraction();
}

bool AccessibilityMathMLElement::isMathFenced() const
{
    return m_renderer && m_renderer->isRenderMathMLFenced();
}

bool AccessibilityMathMLElement::isMathSubscriptSuperscript() const
{
    return m_renderer && m_renderer->isRenderMathMLScripts() && !isMathMultiscript();
}

bool AccessibilityMathMLElement::isMathRow() const
{
    return m_renderer && m_renderer->isRenderMathMLRow() && !isMathRoot();
}

bool AccessibilityMathMLElement::isMathUnderOver() const
{
    return m_renderer && m_renderer->isRenderMathMLUnderOver();
}

bool AccessibilityMathMLElement::isMathSquareRoot() const
{
    return m_renderer && m_renderer->isRenderMathMLSquareRoot();
}

bool AccessibilityMathMLElement::isMathToken() const
{
    return m_renderer && m_renderer->isRenderMathMLToken();
}

bool AccessibilityMathMLElement::isMathRoot() const
{
    return m_renderer && m_renderer->isRenderMathMLRoot();
}

bool AccessibilityMathMLElement::isMathOperator() const
{
    return m_renderer && m_renderer->isRenderMathMLOperator();
}

bool AccessibilityMathMLElement::isAnonymousMathOperator() const
{
    return m_isAnonymousOperator;
}

bool AccessibilityMathMLElement::isMathFenceOperator() const
{
    if (!is<RenderMathMLOperator>(renderer()))
        return false;

    return downcast<RenderMathMLOperator>(*m_renderer).hasOperatorFlag(MathMLOperatorDictionary::Fence);
}

bool AccessibilityMathMLElement::isMathSeparatorOperator() const
{
    if (!is<RenderMathMLOperator>(renderer()))
        return false;

    return downcast<RenderMathMLOperator>(*m_renderer).hasOperatorFlag(MathMLOperatorDictionary::Separator);
}

bool AccessibilityMathMLElement::isMathText() const
{
    return node() && (node()->hasTagName(MathMLNames::mtextTag) || hasTagName(MathMLNames::msTag));
}

bool AccessibilityMathMLElement::isMathNumber() const
{
    return node() && node()->hasTagName(MathMLNames::mnTag);
}

bool AccessibilityMathMLElement::isMathIdentifier() const
{
    return node() && node()->hasTagName(MathMLNames::miTag);
}

bool AccessibilityMathMLElement::isMathMultiscript() const
{
    return node() && node()->hasTagName(MathMLNames::mmultiscriptsTag);
}

bool AccessibilityMathMLElement::isMathTable() const
{
    return node() && node()->hasTagName(MathMLNames::mtableTag);
}

bool AccessibilityMathMLElement::isMathTableRow() const
{
    return node() && (node()->hasTagName(MathMLNames::mtrTag) || hasTagName(MathMLNames::mlabeledtrTag));
}

bool AccessibilityMathMLElement::isMathTableCell() const
{
    return node() && node()->hasTagName(MathMLNames::mtdTag);
}

bool AccessibilityMathMLElement::isMathScriptObject(AccessibilityMathScriptObjectType type) const
{
    AXCoreObject* parent = parentObjectUnignored();
    if (!parent)
        return false;

    return type == AccessibilityMathScriptObjectType::Subscript ? this == parent->mathSubscriptObject() : this == parent->mathSuperscriptObject();
}

bool AccessibilityMathMLElement::isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType type) const
{
    AXCoreObject* parent = parentObjectUnignored();
    if (!parent || !parent->isMathMultiscript())
        return false;

    // The scripts in a MathML <mmultiscripts> element consist of one or more
    // subscript, superscript pairs. In order to determine if this object is
    // a scripted token, we need to examine each set of pairs to see if the
    // this token is present and in the position corresponding with the type.

    AccessibilityMathMultiscriptPairs pairs;
    if (type == AccessibilityMathMultiscriptObjectType::PreSubscript || type == AccessibilityMathMultiscriptObjectType::PreSuperscript)
        parent->mathPrescripts(pairs);
    else
        parent->mathPostscripts(pairs);

    for (const auto& pair : pairs) {
        if (this == pair.first)
            return (type == AccessibilityMathMultiscriptObjectType::PreSubscript || type == AccessibilityMathMultiscriptObjectType::PostSubscript);
        if (this == pair.second)
            return (type == AccessibilityMathMultiscriptObjectType::PreSuperscript || type == AccessibilityMathMultiscriptObjectType::PostSuperscript);
    }

    return false;
}

std::optional<AXCoreObject::AccessibilityChildrenVector> AccessibilityMathMLElement::mathRadicand() 
{
    if (!isMathRoot())
        return std::nullopt;

    const auto& children = this->children();
    if (!children.size())
        return std::nullopt;

    if (isMathSquareRoot())
        return children;
    return { { children[0] } };
}

AXCoreObject* AccessibilityMathMLElement::mathRootIndexObject()
{
    if (!isMathRoot() || isMathSquareRoot())
        return nullptr;

    const auto& children = this->children();
    if (children.size() < 2)
        return nullptr;

    return children[1].get();
}

AXCoreObject* AccessibilityMathMLElement::mathNumeratorObject()
{
    if (!isMathFraction())
        return nullptr;

    const auto& children = this->children();
    if (children.size() != 2)
        return nullptr;

    return children[0].get();
}

AXCoreObject* AccessibilityMathMLElement::mathDenominatorObject()
{
    if (!isMathFraction())
        return nullptr;

    const auto& children = this->children();
    if (children.size() != 2)
        return nullptr;

    return children[1].get();
}

AXCoreObject* AccessibilityMathMLElement::mathUnderObject()
{
    if (!isMathUnderOver() || !node())
        return nullptr;

    const auto& children = this->children();
    if (children.size() < 2)
        return nullptr;

    if (node()->hasTagName(MathMLNames::munderTag) || node()->hasTagName(MathMLNames::munderoverTag))
        return children[1].get();

    return nullptr;
}

AXCoreObject* AccessibilityMathMLElement::mathOverObject()
{
    if (!isMathUnderOver() || !node())
        return nullptr;

    const auto& children = this->children();

    if (children.size() >= 2 && node()->hasTagName(MathMLNames::moverTag))
        return children[1].get();

    if (children.size() >= 3 && node()->hasTagName(MathMLNames::munderoverTag))
        return children[2].get();

    return nullptr;
}

AXCoreObject* AccessibilityMathMLElement::mathBaseObject()
{
    if (!isMathSubscriptSuperscript() && !isMathUnderOver() && !isMathMultiscript())
        return nullptr;

    const auto& children = this->children();
    // The base object in question is always the first child.
    if (children.size() > 0)
        return children[0].get();

    return nullptr;
}

AXCoreObject* AccessibilityMathMLElement::mathSubscriptObject()
{
    if (!isMathSubscriptSuperscript() || !node())
        return nullptr;

    const auto& children = this->children();
    if (children.size() < 2)
        return nullptr;

    if (node()->hasTagName(MathMLNames::msubTag) || node()->hasTagName(MathMLNames::msubsupTag))
        return children[1].get();

    return nullptr;
}

AXCoreObject* AccessibilityMathMLElement::mathSuperscriptObject()
{
    if (!isMathSubscriptSuperscript() || !node())
        return nullptr;

    const auto& children = this->children();
    unsigned count = children.size();

    if (count >= 2 && node()->hasTagName(MathMLNames::msupTag))
        return children[1].get();

    if (count >= 3 && node()->hasTagName(MathMLNames::msubsupTag))
        return children[2].get();

    return nullptr;
}

String AccessibilityMathMLElement::mathFencedOpenString() const
{
    if (!isMathFenced())
        return String();

    return getAttribute(MathMLNames::openAttr);
}

String AccessibilityMathMLElement::mathFencedCloseString() const
{
    if (!isMathFenced())
        return String();

    return getAttribute(MathMLNames::closeAttr);
}

void AccessibilityMathMLElement::mathPrescripts(AccessibilityMathMultiscriptPairs& prescripts)
{
    if (!isMathMultiscript() || !node())
        return;

    bool foundPrescript = false;
    std::pair<AccessibilityObject*, AccessibilityObject*> prescriptPair;
    for (Node* child = node()->firstChild(); child; child = child->nextSibling()) {
        if (foundPrescript) {
            AccessibilityObject* axChild = axObjectCache()->getOrCreate(child);
            if (axChild && axChild->isMathElement()) {
                if (!prescriptPair.first)
                    prescriptPair.first = axChild;
                else {
                    prescriptPair.second = axChild;
                    prescripts.append(prescriptPair);
                    prescriptPair.first = nullptr;
                    prescriptPair.second = nullptr;
                }
            }
        } else if (child->hasTagName(MathMLNames::mprescriptsTag))
            foundPrescript = true;
    }

    // Handle the odd number of pre scripts case.
    if (prescriptPair.first)
        prescripts.append(prescriptPair);
}

void AccessibilityMathMLElement::mathPostscripts(AccessibilityMathMultiscriptPairs& postscripts)
{
    if (!isMathMultiscript() || !node())
        return;

    // In Multiscripts, the post-script elements start after the first element (which is the base)
    // and continue until a <mprescripts> tag is found
    std::pair<AccessibilityObject*, AccessibilityObject*> postscriptPair;
    bool foundBaseElement = false;
    for (Node* child = node()->firstChild(); child; child = child->nextSibling()) {
        if (child->hasTagName(MathMLNames::mprescriptsTag))
            break;

        AccessibilityObject* axChild = axObjectCache()->getOrCreate(child);
        if (axChild && axChild->isMathElement()) {
            if (!foundBaseElement)
                foundBaseElement = true;
            else if (!postscriptPair.first)
                postscriptPair.first = axChild;
            else {
                postscriptPair.second = axChild;
                postscripts.append(postscriptPair);
                postscriptPair.first = nullptr;
                postscriptPair.second = nullptr;
            }
        }
    }

    // Handle the odd number of post scripts case.
    if (postscriptPair.first)
        postscripts.append(postscriptPair);
}

int AccessibilityMathMLElement::mathLineThickness() const
{
    if (!is<RenderMathMLFraction>(renderer()))
        return -1;

    return downcast<RenderMathMLFraction>(*m_renderer).relativeLineThickness();
}

} // namespace WebCore

#endif // ENABLE(MATHML)
