/*
 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
 *           (C) 1997 Torben Weis (weis@kde.org)
 *           (C) 1998 Waldo Bastian (bastian@kde.org)
 *           (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/layout/LayoutTableRow.h"

#include "core/HTMLNames.h"
#include "core/fetch/ImageResource.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutAnalyzer.h"
#include "core/layout/LayoutState.h"
#include "core/layout/LayoutTableCell.h"
#include "core/layout/SubtreeLayoutScope.h"
#include "core/paint/TableRowPainter.h"
#include "core/style/StyleInheritedData.h"

namespace blink {

using namespace HTMLNames;

LayoutTableRow::LayoutTableRow(Element* element)
    : LayoutTableBoxComponent(element)
    , m_rowIndex(unsetRowIndex)
{
    // init LayoutObject attributes
    setInline(false); // our object is not Inline
}

void LayoutTableRow::willBeRemovedFromTree()
{
    LayoutTableBoxComponent::willBeRemovedFromTree();

    section()->setNeedsCellRecalc();
}

void LayoutTableRow::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    DCHECK_EQ(style()->display(), EDisplay::TableRow);

    LayoutTableBoxComponent::styleDidChange(diff, oldStyle);
    propagateStyleToAnonymousChildren();

    if (!oldStyle)
        return;

    if (section() && style()->logicalHeight() != oldStyle->logicalHeight())
        section()->rowLogicalHeightChanged(this);

    if (!parent())
        return;
    LayoutTable* table = this->table();
    if (!table)
        return;

    if (!table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle->border() != style()->border())
        table->invalidateCollapsedBorders();

    if (LayoutTableBoxComponent::doCellsHaveDirtyWidth(*this, *table, diff, *oldStyle)) {
        // If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
        // This only happens when borders are collapsed, since they end up affecting the border sides of the cell
        // itself.
        for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
            if (!childBox->isTableCell())
                continue;
            // TODO(dgrogan) Add a layout test showing that setChildNeedsLayout is needed instead of setNeedsLayout.
            childBox->setChildNeedsLayout();
            childBox->setPreferredLogicalWidthsDirty(MarkOnlyThis);
        }
        // Most table componenents can rely on LayoutObject::styleDidChange
        // to mark the container chain dirty. But LayoutTableSection seems
        // to never clear its dirty bit, which stops the propagation. So
        // anything under LayoutTableSection has to restart the propagation
        // at the table.
        // TODO(dgrogan): Make LayoutTableSection clear its dirty bit.
        table->setPreferredLogicalWidthsDirty();
    }
}

const BorderValue& LayoutTableRow::borderAdjoiningStartCell(const LayoutTableCell* cell) const
{
    ASSERT_UNUSED(cell, cell->isFirstOrLastCellInRow());
    // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
    return style()->borderStart();
}

const BorderValue& LayoutTableRow::borderAdjoiningEndCell(const LayoutTableCell* cell) const
{
    ASSERT_UNUSED(cell, cell->isFirstOrLastCellInRow());
    // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
    return style()->borderEnd();
}

void LayoutTableRow::addChild(LayoutObject* child, LayoutObject* beforeChild)
{
    if (!child->isTableCell()) {
        LayoutObject* last = beforeChild;
        if (!last)
            last = lastCell();
        if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
            LayoutTableCell* lastCell = toLayoutTableCell(last);
            if (beforeChild == lastCell)
                beforeChild = lastCell->firstChild();
            lastCell->addChild(child, beforeChild);
            return;
        }

        if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
            LayoutObject* cell = beforeChild->previousSibling();
            if (cell && cell->isTableCell() && cell->isAnonymous()) {
                cell->addChild(child);
                return;
            }
        }

        // If beforeChild is inside an anonymous cell, insert into the cell.
        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
            last->parent()->addChild(child, beforeChild);
            return;
        }

        LayoutTableCell* cell = LayoutTableCell::createAnonymousWithParent(this);
        addChild(cell, beforeChild);
        cell->addChild(child);
        return;
    }

    if (beforeChild && beforeChild->parent() != this)
        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);

    LayoutTableCell* cell = toLayoutTableCell(child);

    ASSERT(!beforeChild || beforeChild->isTableCell());
    LayoutTableBoxComponent::addChild(cell, beforeChild);

    // Generated content can result in us having a null section so make sure to null check our parent.
    if (parent()) {
        section()->addCell(cell, this);
        // When borders collapse, adding a cell can affect the the width of neighboring cells.
        LayoutTable* enclosingTable = table();
        if (enclosingTable && enclosingTable->collapseBorders()) {
            if (LayoutTableCell* previousCell = cell->previousCell())
                previousCell->setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::TableChanged);
            if (LayoutTableCell* nextCell = cell->nextCell())
                nextCell->setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::TableChanged);
        }
    }

    if (beforeChild || nextRow())
        section()->setNeedsCellRecalc();
}

void LayoutTableRow::layout()
{
    ASSERT(needsLayout());
    LayoutAnalyzer::Scope analyzer(*this);

    // Table rows do not add translation.
    LayoutState state(*this, LayoutSize());

    for (LayoutTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
        SubtreeLayoutScope layouter(*cell);
        if (!cell->needsLayout())
            markChildForPaginationRelayoutIfNeeded(*cell, layouter);
        if (cell->needsLayout())
            cell->layout();
        // We're laying out each cell here to establish its raw logical height so it can be used to
        // figure out the row's height and baseline later on in layoutRows(). As part of that we
        // will layout the cell again if we're in a paginated context and come up with the
        // correct strut. Any strut we come up with here will depend on the old paged layout and will
        // give the cell an invalid height that is not useful for figuring out the raw height of the row.
        if (cell->firstRootBox() && cell->firstRootBox()->paginationStrut())
            cell->setLogicalHeight(cell->logicalHeight() - cell->firstRootBox()->paginationStrut());
    }

    m_overflow.reset();
    addVisualEffectOverflow();
    // We do not call addOverflowFromCell here. The cell are laid out to be
    // measured above and will be sized correctly in a follow-up phase.

    // We only ever need to issue paint invalidations if our cells didn't, which means that they didn't need
    // layout, so we know that our bounds didn't change. This code is just making up for
    // the fact that we did not invalidate paints in setStyle() because we had a layout hint.
    if (selfNeedsLayout()) {
        for (LayoutTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
            // FIXME: Is this needed when issuing paint invalidations after layout?
            cell->setShouldDoFullPaintInvalidation();
        }
    }

    // LayoutTableSection::layoutRows will set our logical height and width later, so it calls updateLayerTransform().
    clearNeedsLayout();
}

// Hit Testing
bool LayoutTableRow::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
    // Table rows cannot ever be hit tested.  Effectively they do not exist.
    // Just forward to our children always.
    for (LayoutTableCell* cell = lastCell(); cell; cell = cell->previousCell()) {
        // FIXME: We have to skip over inline flows, since they can show up inside table rows
        // at the moment (a demoted inline <form> for example). If we ever implement a
        // table-specific hit-test method (which we should do for performance reasons anyway),
        // then we can remove this check.
        if (!cell->hasSelfPaintingLayer()) {
            LayoutPoint cellPoint = flipForWritingModeForChild(cell, accumulatedOffset);
            if (cell->nodeAtPoint(result, locationInContainer, cellPoint, action)) {
                updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
                return true;
            }
        }
    }

    return false;
}

void LayoutTableRow::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const
{
    TableRowPainter(*this).paint(paintInfo, paintOffset);
}

LayoutTableRow* LayoutTableRow::createAnonymous(Document* document)
{
    LayoutTableRow* layoutObject = new LayoutTableRow(nullptr);
    layoutObject->setDocumentForAnonymous(document);
    return layoutObject;
}

LayoutTableRow* LayoutTableRow::createAnonymousWithParent(const LayoutObject* parent)
{
    LayoutTableRow* newRow = LayoutTableRow::createAnonymous(&parent->document());
    RefPtr<ComputedStyle> newStyle = ComputedStyle::createAnonymousStyleWithDisplay(parent->styleRef(), EDisplay::TableRow);
    newRow->setStyle(newStyle.release());
    return newRow;
}

void LayoutTableRow::computeOverflow()
{
    clearAllOverflows();
    addVisualEffectOverflow();
    for (LayoutTableCell* cell = firstCell(); cell; cell = cell->nextCell())
        addOverflowFromCell(cell);
}

void LayoutTableRow::addOverflowFromCell(const LayoutTableCell* cell)
{
    // Non-row-spanning-cells don't create overflow (they are fully contained within this row).
    // TODO(crbug.com/603993): This seems incorrect because cell may have visual effect overflow that should be included in this row.
    if (cell->rowSpan() == 1)
        return;

    // Cells only generates visual overflow.
    LayoutRect cellVisualOverflowRect = cell->visualOverflowRectForPropagation(styleRef());

    // The cell and the row share the section's coordinate system. However
    // the visual overflow should be determined in the coordinate system of
    // the row, that's why we shift it below.
    LayoutUnit cellOffsetLogicalTopDifference = cell->location().y() - location().y();
    cellVisualOverflowRect.move(LayoutUnit(), cellOffsetLogicalTopDifference);

    addContentsVisualOverflow(cellVisualOverflowRect);
}

} // namespace blink
