/*
 * Copyright (C) 2009 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 "AccessibilityARIAGridCell.h"

#include "AccessibilityObject.h"
#include "AccessibilityTable.h"
#include "AccessibilityTableRow.h"
#include "HTMLNames.h"

namespace WebCore {
    
using namespace HTMLNames;

AccessibilityARIAGridCell::AccessibilityARIAGridCell(RenderObject* renderer)
    : AccessibilityTableCell(renderer)
{
}

AccessibilityARIAGridCell::~AccessibilityARIAGridCell()
{
}

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

AccessibilityTable* AccessibilityARIAGridCell::parentTable() const
{
    // ARIA gridcells may have multiple levels of unignored ancestors that are not the parent table,
    // including rows and interactive rowgroups. In addition, poorly-formed grids may contain elements
    // which pass the tests for inclusion.
    for (AccessibilityObject* parent = parentObjectUnignored(); parent; parent = parent->parentObjectUnignored()) {
        if (is<AccessibilityTable>(*parent) && downcast<AccessibilityTable>(*parent).isExposableThroughAccessibility())
            return downcast<AccessibilityTable>(parent);
    }

    return nullptr;
}
    
void AccessibilityARIAGridCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange) const
{
    AccessibilityObject* parent = parentObjectUnignored();
    if (!parent)
        return;

    if (is<AccessibilityTableRow>(*parent)) {
        // We already got a table row, use its API.
        rowRange.first = downcast<AccessibilityTableRow>(*parent).rowIndex();
    } else if (is<AccessibilityTable>(*parent) && downcast<AccessibilityTable>(*parent).isExposableThroughAccessibility()) {
        // We reached the parent table, so we need to inspect its
        // children to determine the row index for the cell in it.
        unsigned columnCount = downcast<AccessibilityTable>(*parent).columnCount();
        if (!columnCount)
            return;

        const auto& siblings = parent->children();
        unsigned childrenSize = siblings.size();
        for (unsigned k = 0; k < childrenSize; ++k) {
            if (siblings[k].get() == this) {
                rowRange.first = k / columnCount;
                break;
            }
        }
    }

    // ARIA 1.1, aria-rowspan attribute is intended for cells and gridcells which are not contained in a native table.
    // So we should check for that attribute here.
    rowRange.second = ariaRowSpanWithRowIndex(rowRange.first);
}

unsigned AccessibilityARIAGridCell::ariaRowSpanWithRowIndex(unsigned rowIndex) const
{
    unsigned rowSpan = AccessibilityTableCell::ariaRowSpan();
    AccessibilityObject* parent = parentObjectUnignored();
    if (!parent)
        return 1;
    
    // Setting the value to 0 indicates that the cell or gridcell is to span all the remaining rows in the row group.
    if (!rowSpan) {
        // rowSpan defaults to 1.
        rowSpan = 1;
        if (AccessibilityObject* parentRowGroup = this->parentRowGroup()) {
            // If the row group is the parent table, we use total row count to calculate the span.
            if (is<AccessibilityTable>(*parentRowGroup))
                rowSpan = downcast<AccessibilityTable>(*parentRowGroup).rowCount() - rowIndex;
            // Otherwise, we have to get the index for the current row within the parent row group.
            else if (is<AccessibilityTableRow>(*parent)) {
                const auto& siblings = parentRowGroup->children();
                unsigned rowCount = siblings.size();
                for (unsigned k = 0; k < rowCount; ++k) {
                    if (siblings[k].get() == parent) {
                        rowSpan = rowCount - k;
                        break;
                    }
                }
            }
        }
    }

    return rowSpan;
}

void AccessibilityARIAGridCell::columnIndexRange(std::pair<unsigned, unsigned>& columnRange) const
{
    AccessibilityObject* parent = parentObjectUnignored();
    if (!parent)
        return;

    if (!is<AccessibilityTableRow>(*parent)
        && !(is<AccessibilityTable>(*parent) && downcast<AccessibilityTable>(*parent).isExposableThroughAccessibility()))
        return;

    const AccessibilityChildrenVector& siblings = parent->children();
    unsigned childrenSize = siblings.size();
    for (unsigned k = 0; k < childrenSize; ++k) {
        if (siblings[k].get() == this) {
            columnRange.first = k;
            break;
        }
    }
    
    // ARIA 1.1, aria-colspan attribute is intended for cells and gridcells which are not contained in a native table.
    // So we should check for that attribute here.
    columnRange.second = ariaColumnSpan();
}

AccessibilityObject* AccessibilityARIAGridCell::parentRowGroup() const
{
    for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
        if (parent->hasTagName(theadTag) || parent->hasTagName(tbodyTag) || parent->hasTagName(tfootTag) || parent->roleValue() == RowGroupRole)
            return parent;
    }
    
    // If there's no row group found, we use the parent table as the row group.
    return parentTable();
}
  
} // namespace WebCore
