/*
 * Copyright (C) 2008 Apple Inc. 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.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 "AccessibilityTableRow.h"

#include "AXObjectCache.h"
#include "AccessibilityTable.h"
#include "AccessibilityTableCell.h"
#include "HTMLNames.h"
#include "HTMLTableRowElement.h"
#include "RenderObject.h"
#include "RenderTableCell.h"
#include "RenderTableRow.h"

namespace WebCore {
    
using namespace HTMLNames;
    
AccessibilityTableRow::AccessibilityTableRow(RenderObject* renderer)
    : AccessibilityRenderObject(renderer)
{
}

AccessibilityTableRow::~AccessibilityTableRow() = default;

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

AccessibilityRole AccessibilityTableRow::determineAccessibilityRole()
{
    if (!isTableRow())
        return AccessibilityRenderObject::determineAccessibilityRole();

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

    return AccessibilityRole::Row;
}

bool AccessibilityTableRow::isTableRow() const
{
    AccessibilityObject* table = parentTable();
    return is<AccessibilityTable>(table) && downcast<AccessibilityTable>(*table).isExposable();
}
    
AccessibilityObject* AccessibilityTableRow::observableObject() const
{
    // This allows the table to be the one who sends notifications about tables.
    return parentTable();
}
    
bool AccessibilityTableRow::computeAccessibilityIsIgnored() const
{    
    AccessibilityObjectInclusion decision = defaultObjectInclusion();
    if (decision == AccessibilityObjectInclusion::IncludeObject)
        return false;
    if (decision == AccessibilityObjectInclusion::IgnoreObject)
        return true;
    
    if (!isTableRow())
        return AccessibilityRenderObject::computeAccessibilityIsIgnored();

    return false;
}
    
AccessibilityTable* AccessibilityTableRow::parentTable() const
{
    // The parent table might not be the direct ancestor of the row unfortunately. ARIA states that role="grid" should
    // only have "row" elements, but if not, we still should handle it gracefully by finding the right table.
    for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
        // If this is a non-anonymous table object, but not an accessibility table, we should stop because we don't want to
        // choose another ancestor table as this row's table.
        if (is<AccessibilityTable>(*parent)) {
            auto& parentTable = downcast<AccessibilityTable>(*parent);
            if (parentTable.isExposable())
                return &parentTable;
            if (parentTable.node())
                break;
        }
    }
    
    return nullptr;
}
    
AXCoreObject* AccessibilityTableRow::headerObject()
{
    if (!m_renderer || !m_renderer->isTableRow())
        return nullptr;
    
    const auto& rowChildren = children();
    if (!rowChildren.size())
        return nullptr;
    
    // check the first element in the row to see if it is a TH element
    AXCoreObject* cell = rowChildren[0].get();
    if (!is<AccessibilityTableCell>(*cell))
        return nullptr;
    
    RenderObject* cellRenderer = downcast<AccessibilityTableCell>(*cell).renderer();
    if (!cellRenderer)
        return nullptr;
    
    Node* cellNode = cellRenderer->node();
    if (!cellNode || !cellNode->hasTagName(thTag))
        return nullptr;
    
    // Verify that the row header is not part of an entire row of headers.
    // In that case, it is unlikely this is a row header.
    bool allHeadersInRow = true;
    for (const auto& cell : rowChildren) {
        if (cell->node() && !cell->node()->hasTagName(thTag)) {
            allHeadersInRow = false;
            break;
        }
    }
    if (allHeadersInRow)
        return nullptr;
    
    return cell;
}
    
void AccessibilityTableRow::addChildren()
{
    AccessibilityRenderObject::addChildren();
    
    // "ARIA 1.1, If the set of columns which is present in the DOM is contiguous, and if there are no cells which span more than one row or
    // column in that set, then authors may place aria-colindex on each row, setting the value to the index of the first column of the set."
    // Update child cells' axColIndex if there's an aria-colindex value set for the row. So the cell doesn't have to go through the siblings
    // to calculate the index.
    int colIndex = axColumnIndex();
    if (colIndex == -1)
        return;
    
    unsigned index = 0;
    for (const auto& cell : children()) {
        if (is<AccessibilityTableCell>(*cell))
            downcast<AccessibilityTableCell>(*cell).setAXColIndexFromRow(colIndex + index);
        index++;
    }
}

int AccessibilityTableRow::axColumnIndex() const
{
    const AtomString& colIndexValue = getAttribute(aria_colindexAttr);
    if (colIndexValue.toInt() >= 1)
        return colIndexValue.toInt();
    
    return -1;
}

int AccessibilityTableRow::axRowIndex() const
{
    const AtomString& rowIndexValue = getAttribute(aria_rowindexAttr);
    if (rowIndexValue.toInt() >= 1)
        return rowIndexValue.toInt();
    
    return -1;
}
    
} // namespace WebCore
