/*
 * 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/html_names.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutAnalyzer.h"
#include "core/layout/LayoutState.h"
#include "core/layout/LayoutTableCell.h"
#include "core/layout/LayoutView.h"
#include "core/layout/SubtreeLayoutScope.h"
#include "core/paint/TableRowPainter.h"

namespace blink {

using namespace HTMLNames;

LayoutTableRow::LayoutTableRow(Element* element)
    : LayoutTableBoxComponent(element), row_index_(kUnsetRowIndex) {
  // init LayoutObject attributes
  SetInline(false);  // our object is not Inline
}

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

  Section()->SetNeedsCellRecalc();
}

void LayoutTableRow::StyleDidChange(StyleDifference diff,
                                    const ComputedStyle* old_style) {
  DCHECK_EQ(Style()->Display(), EDisplay::kTableRow);

  LayoutTableBoxComponent::StyleDidChange(diff, old_style);
  PropagateStyleToAnonymousChildren();

  if (!old_style)
    return;

  if (Section() && Style()->LogicalHeight() != old_style->LogicalHeight())
    Section()->RowLogicalHeightChanged(this);

  if (!Parent())
    return;
  LayoutTable* table = Table();
  if (!table)
    return;

  LayoutTableBoxComponent::InvalidateCollapsedBordersOnStyleChange(
      *this, *table, diff, *old_style);

  if (LayoutTableBoxComponent::DoCellsHaveDirtyWidth(*this, *table, diff,
                                                     *old_style)) {
    // 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* child_box = FirstChildBox(); child_box;
         child_box = child_box->NextSiblingBox()) {
      if (!child_box->IsTableCell())
        continue;
      // TODO(dgrogan) Add a layout test showing that setChildNeedsLayout is
      // needed instead of setNeedsLayout.
      child_box->SetChildNeedsLayout();
      child_box->SetPreferredLogicalWidthsDirty(kMarkOnlyThis);
    }
    // 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();
  }

  // When a row gets collapsed or uncollapsed, it's necessary to check all the
  // rows to find any cell that may span the current row.
  if ((old_style->Visibility() == EVisibility::kCollapse) !=
      (Style()->Visibility() == EVisibility::kCollapse)) {
    for (LayoutTableRow* row = Section()->FirstRow(); row;
         row = row->NextRow()) {
      for (LayoutTableCell* cell = row->FirstCell(); cell;
           cell = cell->NextCell()) {
        if (!cell->IsSpanningCollapsedRow())
          continue;
        unsigned rowIndex = RowIndex();
        unsigned spanStart = cell->RowIndex();
        unsigned spanEnd = spanStart + cell->ResolvedRowSpan();
        if (spanStart <= rowIndex && rowIndex <= spanEnd)
          cell->SetCellChildrenNeedLayout();
      }
    }
  }
}

void LayoutTableRow::AddChild(LayoutObject* child, LayoutObject* before_child) {
  if (!child->IsTableCell()) {
    LayoutObject* last = before_child;
    if (!last)
      last = LastCell();
    if (last && last->IsAnonymous() && last->IsTableCell() &&
        !last->IsBeforeOrAfterContent()) {
      LayoutTableCell* last_cell = ToLayoutTableCell(last);
      if (before_child == last_cell)
        before_child = last_cell->FirstChild();
      last_cell->AddChild(child, before_child);
      return;
    }

    if (before_child && !before_child->IsAnonymous() &&
        before_child->Parent() == this) {
      LayoutObject* cell = before_child->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, before_child);
      return;
    }

    LayoutTableCell* cell = LayoutTableCell::CreateAnonymousWithParent(this);
    AddChild(cell, before_child);
    cell->AddChild(child);
    return;
  }

  if (before_child && before_child->Parent() != this)
    before_child = SplitAnonymousBoxesAroundChild(before_child);

  LayoutTableCell* cell = ToLayoutTableCell(child);

  DCHECK(!before_child || before_child->IsTableCell());
  LayoutTableBoxComponent::AddChild(cell, before_child);

  // 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* enclosing_table = Table();
    if (enclosing_table && enclosing_table->ShouldCollapseBorders()) {
      enclosing_table->InvalidateCollapsedBorders();
      if (LayoutTableCell* previous_cell = cell->PreviousCell())
        previous_cell->SetNeedsLayoutAndPrefWidthsRecalc(
            LayoutInvalidationReason::kTableChanged);
      if (LayoutTableCell* next_cell = cell->NextCell())
        next_cell->SetNeedsLayoutAndPrefWidthsRecalc(
            LayoutInvalidationReason::kTableChanged);
    }
  }

  if (before_child || NextRow() || !cell->ParsedRowSpan())
    Section()->SetNeedsCellRecalc();
}

void LayoutTableRow::UpdateLayout() {
  DCHECK(NeedsLayout());
  LayoutAnalyzer::Scope analyzer(*this);
  bool paginated = View()->GetLayoutState()->IsPaginated();

  for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell()) {
    SubtreeLayoutScope layouter(*cell);
    cell->SetLogicalTop(LogicalTop());
    if (!cell->NeedsLayout())
      Section()->MarkChildForPaginationRelayoutIfNeeded(*cell, layouter);
    if (cell->NeedsLayout()) {
      // If we are laying out the cell's children clear its intrinsic
      // padding so it doesn't skew the position of the content.
      if (cell->CellChildrenNeedLayout())
        cell->ClearIntrinsicPadding();
      cell->UpdateLayout();
    }
    if (paginated)
      Section()->UpdateFragmentationInfoForChild(*cell);
  }

  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& location_in_container,
                                 const LayoutPoint& accumulated_offset,
                                 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 cell_point =
          FlipForWritingModeForChild(cell, accumulated_offset);
      if (cell->NodeAtPoint(result, location_in_container, cell_point,
                            action)) {
        UpdateHitTestResult(
            result, location_in_container.Point() - ToLayoutSize(cell_point));
        return true;
      }
    }
  }

  return false;
}

LayoutBox::PaginationBreakability LayoutTableRow::GetPaginationBreakability()
    const {
  PaginationBreakability breakability =
      LayoutTableBoxComponent::GetPaginationBreakability();
  if (breakability == kAllowAnyBreaks) {
    // Even if the row allows us to break inside, we will want to prevent that
    // if we have a header group that wants to appear at the top of each page.
    if (const LayoutTableSection* header = Table()->Header())
      breakability = header->GetPaginationBreakability();
  }
  return breakability;
}

void LayoutTableRow::Paint(const PaintInfo& paint_info,
                           const LayoutPoint& paint_offset) const {
  TableRowPainter(*this).Paint(paint_info, paint_offset);
}

LayoutTableRow* LayoutTableRow::CreateAnonymous(Document* document) {
  LayoutTableRow* layout_object = new LayoutTableRow(nullptr);
  layout_object->SetDocumentForAnonymous(document);
  return layout_object;
}

LayoutTableRow* LayoutTableRow::CreateAnonymousWithParent(
    const LayoutObject* parent) {
  LayoutTableRow* new_row =
      LayoutTableRow::CreateAnonymous(&parent->GetDocument());
  scoped_refptr<ComputedStyle> new_style =
      ComputedStyle::CreateAnonymousStyleWithDisplay(parent->StyleRef(),
                                                     EDisplay::kTableRow);
  new_row->SetStyle(std::move(new_style));
  return new_row;
}

void LayoutTableRow::ComputeOverflow() {
  ClearAllOverflows();
  AddVisualEffectOverflow();
  for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell())
    AddOverflowFromCell(cell);
}

void LayoutTableRow::AddOverflowFromCell(const LayoutTableCell* cell) {
  // Table row paints its background behind cells. If the cell spans multiple
  // rows, the row's visual rect should be expanded to cover the cell.
  // Here don't check background existence to avoid requirement to invalidate
  // overflow on change of background existence.
  if (cell->ResolvedRowSpan() > 1) {
    LayoutRect cell_background_rect = cell->FrameRect();
    cell_background_rect.MoveBy(-Location());
    AddSelfVisualOverflow(cell_background_rect);
  }

  // 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 the rects by cell_row_offset below.
  LayoutSize cell_row_offset = cell->Location() - Location();

  // Let the row's self visual overflow cover the cell's whole collapsed
  // borders. This ensures correct raster invalidation on row border style
  // change.
  if (const auto* collapsed_borders = cell->GetCollapsedBorderValues()) {
    LayoutRect collapsed_border_rect =
        cell->RectForOverflowPropagation(collapsed_borders->LocalVisualRect());
    collapsed_border_rect.Move(cell_row_offset);
    AddSelfVisualOverflow(collapsed_border_rect);
  }

  // Should propagate cell's overflow to row if the cell has row span or has
  // overflow.
  if (cell->ResolvedRowSpan() == 1 && !cell->HasOverflowModel())
    return;

  LayoutRect cell_visual_overflow_rect =
      cell->VisualOverflowRectForPropagation();
  cell_visual_overflow_rect.Move(cell_row_offset);
  AddContentsVisualOverflow(cell_visual_overflow_rect);

  LayoutRect cell_layout_overflow_rect =
      cell->LayoutOverflowRectForPropagation(this);
  cell_layout_overflow_rect.Move(cell_row_offset);
  AddLayoutOverflow(cell_layout_overflow_rect);
}

bool LayoutTableRow::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const {
  return LayoutTableBoxComponent::
             PaintedOutputOfObjectHasNoEffectRegardlessOfSize() &&
         // Row paints collapsed borders.
         !Table()->HasCollapsedBorders();
}

}  // namespace blink
