/*
 * 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 "AccessibilityARIAGrid.h"

#include "AXObjectCache.h"
#include "AccessibilityARIAGridRow.h"
#include "AccessibilityTableCell.h"
#include "AccessibilityTableColumn.h"
#include "AccessibilityTableHeaderContainer.h"
#include "AccessibilityTableRow.h"
#include "RenderObject.h"
#include "RenderTableSection.h"

namespace WebCore {

AccessibilityARIAGrid::AccessibilityARIAGrid(RenderObject* renderer)
    : AccessibilityTable(renderer)
{
}

AccessibilityARIAGrid::~AccessibilityARIAGrid()
{
}

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

bool AccessibilityARIAGrid::addTableCellChild(AccessibilityObject* child, HashSet<AccessibilityObject*>& appendedRows, unsigned& columnCount)
{
    if (!child || (!is<AccessibilityTableRow>(*child) && !is<AccessibilityARIAGridRow>(*child)))
        return false;
        
    auto& row = downcast<AccessibilityTableRow>(*child);
    if (appendedRows.contains(&row))
        return false;
        
    // store the maximum number of columns
    unsigned rowCellCount = row.children().size();
    if (rowCellCount > columnCount)
        columnCount = rowCellCount;
    
    row.setRowIndex((int)m_rows.size());
    m_rows.append(&row);

    // Try adding the row if it's not ignoring accessibility,
    // otherwise add its children (the cells) as the grid's children.
    if (!row.accessibilityIsIgnored())
        m_children.append(&row);
    else
        m_children.appendVector(row.children());

    appendedRows.add(&row);
    return true;
}

void AccessibilityARIAGrid::addRowDescendant(AccessibilityObject* rowChild, HashSet<AccessibilityObject*>& appendedRows, unsigned& columnCount)
{
    if (!rowChild)
        return;

    if (!rowChild->isTableRow() || !rowChild->node()) {
        // Although a "grid" should have rows as its direct descendants, if this is not a table row,
        // or this row is anonymous, dive deeper into the descendants to try to find a valid row.
        for (const auto& child : rowChild->children())
            addRowDescendant(child.get(), appendedRows, columnCount);
    } else
        addTableCellChild(rowChild, appendedRows, columnCount);
}

void AccessibilityARIAGrid::addChildren()
{
    ASSERT(!m_haveChildren); 
    
    if (!isExposableThroughAccessibility()) {
        AccessibilityRenderObject::addChildren();
        return;
    }
    
    m_haveChildren = true;
    if (!m_renderer)
        return;
    
    AXObjectCache* axCache = m_renderer->document().axObjectCache();
    
    // Add the children rows but be mindful in case there are footer sections in this table.
    HashSet<AccessibilityObject*> appendedRows;
    unsigned columnCount = 0;
    AccessibilityChildrenVector footerSections;
    for (RefPtr<AccessibilityObject> child = firstChild(); child; child = child->nextSibling()) {
        bool footerSection = false;
        if (RenderObject* childRenderer = child->renderer()) {
            if (is<RenderTableSection>(*childRenderer)) {
                RenderTableSection& childSection = downcast<RenderTableSection>(*childRenderer);
                if (&childSection == childSection.table()->footer()) {
                    footerSections.append(child);
                    footerSection = true;
                }
            }
        }
        if (!footerSection)
            addRowDescendant(child.get(), appendedRows, columnCount);
    }
    
    for (const auto& footerSection : footerSections)
        addRowDescendant(footerSection.get(), appendedRows, columnCount);
    
    // make the columns based on the number of columns in the first body
    for (unsigned i = 0; i < columnCount; ++i) {
        auto& column = downcast<AccessibilityTableColumn>(*axCache->getOrCreate(ColumnRole));
        column.setColumnIndex(static_cast<int>(i));
        column.setParent(this);
        m_columns.append(&column);
        if (!column.accessibilityIsIgnored())
            m_children.append(&column);
    }
    
    AccessibilityObject* headerContainerObject = headerContainer();
    if (headerContainerObject && !headerContainerObject->accessibilityIsIgnored())
        m_children.append(headerContainerObject);
}
    
} // namespace WebCore
