/*
 * Copyright (C) 2008, 2011, 2012, 2013 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 "HTMLTableRowsCollection.h"

#include "ElementIterator.h"
#include "HTMLNames.h"
#include "HTMLTableElement.h"
#include "HTMLTableRowElement.h"

namespace WebCore {

using namespace HTMLNames;

static inline void assertRowIsInTable(HTMLTableElement& table, HTMLTableRowElement* row)
{
#if !ASSERT_DISABLED
    UNUSED_PARAM(table);
    UNUSED_PARAM(row);
#else
    if (!row)
        return;
    if (row->parentNode() == &table)
        return;
    ASSERT(row->parentNode());
    ASSERT(row->parentNode()->hasTagName(theadTag) || row->parentNode()->hasTagName(tbodyTag) || row->parentNode()->hasTagName(tfootTag));
    ASSERT(row->parentNode()->parentNode() == &table);
#endif
}

static inline bool isInSection(HTMLTableRowElement& row, const HTMLQualifiedName& sectionTag)
{
    // Because we know that the parent is a table or a section, it's safe to cast it to an HTMLElement
    // giving us access to the faster hasTagName overload from that class.
    return downcast<HTMLElement>(*row.parentNode()).hasTagName(sectionTag);
}

HTMLTableRowElement* HTMLTableRowsCollection::rowAfter(HTMLTableElement& table, HTMLTableRowElement* previous)
{
    // The HTMLCollection caching mechanism, along with the code in this class, will guarantee that the previous row
    // is an immediate child of either the table, or a table section that is itself an immediate child of the table.
    assertRowIsInTable(table, previous);

    // Start by looking for the next row in this section. Continue only if there is none.
    if (previous && previous->parentNode() != &table) {
        auto childRows = childrenOfType<HTMLTableRowElement>(*previous->parentNode());
        auto row = childRows.beginAt(*previous);
        if (++row != childRows.end())
            return &*row;
    }

    RefPtr<Element> child;

    // If still looking at head sections, find the first row in the next head section.
    if (!previous)
        child = ElementTraversal::firstChild(table);
    else if (isInSection(*previous, theadTag))
        child = ElementTraversal::nextSibling(*previous->parentNode());
    for (; child; child = ElementTraversal::nextSibling(*child)) {
        if (child->hasTagName(theadTag)) {
            if (auto row = childrenOfType<HTMLTableRowElement>(*child).first())
                return row;
        }
    }

    // If still looking at top level and bodies, find the next row in top level or the first in the next body section.
    if (!previous || isInSection(*previous, theadTag))
        child = ElementTraversal::firstChild(table);
    else if (previous->parentNode() == &table)
        child = ElementTraversal::nextSibling(*previous);
    else if (isInSection(*previous, tbodyTag))
        child = ElementTraversal::nextSibling(*previous->parentNode());
    for (; child; child = ElementTraversal::nextSibling(*child)) {
        if (is<HTMLTableRowElement>(*child))
            return downcast<HTMLTableRowElement>(child.get());
        if (child->hasTagName(tbodyTag)) {
            if (auto row = childrenOfType<HTMLTableRowElement>(*child).first())
                return row;
        }
    }

    // Find the first row in the next foot section.
    if (!previous || !isInSection(*previous, tfootTag))
        child = ElementTraversal::firstChild(table);
    else
        child = ElementTraversal::nextSibling(*previous->parentNode());
    for (; child; child = ElementTraversal::nextSibling(*child)) {
        if (child->hasTagName(tfootTag)) {
            if (auto row = childrenOfType<HTMLTableRowElement>(*child).first())
                return row;
        }
    }

    return nullptr;
}

HTMLTableRowElement* HTMLTableRowsCollection::lastRow(HTMLTableElement& table)
{
    for (auto* child = ElementTraversal::lastChild(table); child; child = ElementTraversal::previousSibling(*child)) {
        if (child->hasTagName(tfootTag)) {
            if (auto* row = childrenOfType<HTMLTableRowElement>(*child).last())
                return row;
        }
    }

    for (auto* child = ElementTraversal::lastChild(table); child; child = ElementTraversal::previousSibling(*child)) {
        if (is<HTMLTableRowElement>(*child))
            return downcast<HTMLTableRowElement>(child);
        if (child->hasTagName(tbodyTag)) {
            if (auto* row = childrenOfType<HTMLTableRowElement>(*child).last())
                return row;
        }
    }

    for (auto* child = ElementTraversal::lastChild(table); child; child = ElementTraversal::previousSibling(*child)) {
        if (child->hasTagName(theadTag)) {
            if (auto* row = childrenOfType<HTMLTableRowElement>(*child).last())
                return row;
        }
    }

    return nullptr;
}

HTMLTableRowsCollection::HTMLTableRowsCollection(HTMLTableElement& table)
    : CachedHTMLCollection<HTMLTableRowsCollection, CollectionTypeTraits<TableRows>::traversalType>(table, TableRows)
{
}

Ref<HTMLTableRowsCollection> HTMLTableRowsCollection::create(HTMLTableElement& table, CollectionType type)
{
    ASSERT_UNUSED(type, type == TableRows);
    return adoptRef(*new HTMLTableRowsCollection(table));
}

Element* HTMLTableRowsCollection::customElementAfter(Element* previous) const
{
    return rowAfter(const_cast<HTMLTableElement&>(tableElement()), downcast<HTMLTableRowElement>(previous));
}

}
