/*
 * Copyright (C) 2019 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 "TableFormattingContext.h"

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

#include "LayoutBox.h"
#include "LayoutChildIterator.h"
#include "TableFormattingState.h"
#include <wtf/IsoMallocInlines.h>

namespace WebCore {
namespace Layout {

WTF_MAKE_ISO_ALLOCATED_IMPL(TableFormattingContext);

// FIXME: This is temporary. Remove this function when table formatting is complete.
void TableFormattingContext::initializeDisplayBoxToBlank(Display::Box& displayBox) const
{
    displayBox.setBorder({ });
    displayBox.setPadding({ });
    displayBox.setHorizontalMargin({ });
    displayBox.setHorizontalComputedMargin({ });
    displayBox.setVerticalMargin({ { }, { } });
    displayBox.setTopLeft({ });
    displayBox.setContentBoxWidth({ });
    displayBox.setContentBoxHeight({ });
}

// https://www.w3.org/TR/css-tables-3/#table-layout-algorithm
TableFormattingContext::TableFormattingContext(const Container& formattingContextRoot, TableFormattingState& formattingState)
    : FormattingContext(formattingContextRoot, formattingState)
{
}

void TableFormattingContext::layoutInFlowContent()
{
    auto& grid = formattingState().tableGrid();
    auto& cellList = grid.cells();
    auto& columnList = grid.columnsContext().columns();
    ASSERT(!cellList.isEmpty());
    // Layout and position each table cell (and compute row height as well).
    for (auto& cell : cellList) {
        auto& cellLayoutBox = cell->tableCellBox;
        layoutTableCellBox(cellLayoutBox, columnList.at(cell->position.x()));
        // FIXME: Add support for column and row spanning and this requires a 2 pass layout.
        auto& row = grid.rows().at(cell->position.y());
        row.setLogicalHeight(std::max(row.logicalHeight(), geometryForBox(cellLayoutBox).marginBoxHeight()));
    }
    // This is after the second pass when cell heights are fully computed.
    auto rowLogicalTop = grid.verticalSpacing();
    for (auto& row : grid.rows()) {
        row.setLogicalTop(rowLogicalTop);
        rowLogicalTop += (row.logicalHeight() + grid.verticalSpacing());
    }

    // Finalize size and position.
    positionTableCells();
    setComputedGeometryForSections();
    setComputedGeometryForRows();
}

void TableFormattingContext::layoutTableCellBox(const Box& cellLayoutBox, const TableGrid::Column& column)
{
    auto& cellDisplayBox = formattingState().displayBox(cellLayoutBox);
    computeBorderAndPadding(cellLayoutBox);
    // Margins do not apply to internal table elements.
    cellDisplayBox.setHorizontalMargin({ });
    cellDisplayBox.setHorizontalComputedMargin({ });
    // Don't know the actual position yet.
    cellDisplayBox.setTopLeft({ });
    cellDisplayBox.setContentBoxWidth(column.logicalWidth() - cellDisplayBox.horizontalMarginBorderAndPadding());

    ASSERT(cellLayoutBox.establishesBlockFormattingContext());
    if (is<Container>(cellLayoutBox))
        LayoutContext::createFormattingContext(downcast<Container>(cellLayoutBox), layoutState())->layoutInFlowContent();
    cellDisplayBox.setVerticalMargin({ { }, { } });
    cellDisplayBox.setContentBoxHeight(geometry().tableCellHeightAndMargin(cellLayoutBox).height);
    // FIXME: Check what to do with out-of-flow content.
}

void TableFormattingContext::positionTableCells()
{
    auto& grid = formattingState().tableGrid();
    auto& rowList = grid.rows();
    auto& columnList = grid.columnsContext().columns();
    for (auto& cell : grid.cells()) {
        auto& cellDisplayBox = formattingState().displayBox(cell->tableCellBox);
        cellDisplayBox.setTop(rowList.at(cell->position.y()).logicalTop());
        cellDisplayBox.setLeft(columnList.at(cell->position.x()).logicalLeft());
    }
}

void TableFormattingContext::setComputedGeometryForRows()
{
    auto& grid = formattingState().tableGrid();
    auto rowWidth = grid.columnsContext().logicalWidth() + 2 * grid.horizontalSpacing();

    auto& rowList = grid.rows();
    for (auto& row : rowList) {
        auto& rowDisplayBox = formattingState().displayBox(row.box());
        initializeDisplayBoxToBlank(rowDisplayBox);
        rowDisplayBox.setContentBoxHeight(row.logicalHeight());
        rowDisplayBox.setContentBoxWidth(rowWidth);
        rowDisplayBox.setTop(row.logicalTop());
    }
}

void TableFormattingContext::setComputedGeometryForSections()
{
    auto& grid = formattingState().tableGrid();
    auto sectionWidth = grid.columnsContext().logicalWidth() + 2 * grid.horizontalSpacing();

    for (auto& section : childrenOfType<Box>(root())) {
        auto& sectionDisplayBox = formattingState().displayBox(section);
        initializeDisplayBoxToBlank(sectionDisplayBox);
        // FIXME: Size table sections properly.
        sectionDisplayBox.setContentBoxWidth(sectionWidth);
        sectionDisplayBox.setContentBoxHeight(grid.rows().last().logicalBottom() + grid.verticalSpacing());
    }
}

FormattingContext::IntrinsicWidthConstraints TableFormattingContext::computedIntrinsicWidthConstraints()
{
    // Tables have a slighty different concept of shrink to fit. It's really only different with non-auto "width" values, where
    // a generic shrink-to fit block level box like a float box would be just sized to the computed value of "width", tables
    // can actually be streched way over.

    // 1. Ensure each cell slot is occupied by at least one cell.
    ensureTableGrid();
    // 2. Compute the minimum width of each column.
    computePreferredWidthForColumns();
    // 3. Compute the width of the table.
    auto width = computedTableWidth();
    // This is the actual computed table width that we want to present as min/max width.
    formattingState().setIntrinsicWidthConstraints({ width, width });
    return { width, width };
}

void TableFormattingContext::ensureTableGrid()
{
    auto& tableWrapperBox = root();
    auto& tableGrid = formattingState().tableGrid();
    tableGrid.setHorizontalSpacing(LayoutUnit { tableWrapperBox.style().horizontalBorderSpacing() });
    tableGrid.setVerticalSpacing(LayoutUnit { tableWrapperBox.style().verticalBorderSpacing() });

    for (auto* section = tableWrapperBox.firstChild(); section; section = section->nextSibling()) {
        ASSERT(section->isTableHeader() || section->isTableBody() || section->isTableFooter());
        for (auto* row = downcast<Container>(*section).firstChild(); row; row = row->nextSibling()) {
            ASSERT(row->isTableRow());
            for (auto* cell = downcast<Container>(*row).firstChild(); cell; cell = cell->nextSibling()) {
                ASSERT(cell->isTableCell());
                tableGrid.appendCell(*cell);
            }
        }
    }
}

void TableFormattingContext::computePreferredWidthForColumns()
{
    auto& formattingState = this->formattingState();
    auto& grid = formattingState.tableGrid();

    // 1. Calculate the minimum content width (MCW) of each cell: the formatted content may span any number of lines but may not overflow the cell box.
    //    If the specified 'width' (W) of the cell is greater than MCW, W is the minimum cell width. A value of 'auto' means that MCW is the minimum cell width.
    //    Also, calculate the "maximum" cell width of each cell: formatting the content without breaking lines other than where explicit line breaks occur.
    for (auto& cell : grid.cells()) {
        auto& tableCellBox = cell->tableCellBox;
        ASSERT(tableCellBox.establishesFormattingContext());

        auto intrinsicWidth = formattingState.intrinsicWidthConstraintsForBox(tableCellBox);
        if (!intrinsicWidth) {
            intrinsicWidth = IntrinsicWidthConstraints { };
            if (is<Container>(tableCellBox))
                intrinsicWidth = LayoutContext::createFormattingContext(downcast<Container>(tableCellBox), layoutState())->computedIntrinsicWidthConstraints();
            intrinsicWidth = geometry().constrainByMinMaxWidth(tableCellBox, *intrinsicWidth);
            auto border = geometry().computedBorder(tableCellBox);
            auto padding = *geometry().computedPadding(tableCellBox, UsedHorizontalValues { UsedHorizontalValues::Constraints { { }, { } } });

            intrinsicWidth->expand(border.horizontal.width() + padding.horizontal.width());
            formattingState.setIntrinsicWidthConstraintsForBox(tableCellBox, *intrinsicWidth);
        }

        auto columnSpan = cell->size.width();
        auto slotIntrinsicWidth = FormattingContext::IntrinsicWidthConstraints { intrinsicWidth->minimum / columnSpan, intrinsicWidth->maximum / columnSpan };
        auto initialPosition = cell->position;
        for (auto i = 0; i < columnSpan; ++i)
            grid.slot({ initialPosition.x() + i, initialPosition.y() })->widthConstraints = slotIntrinsicWidth;
    }
    // 2. For each column, determine a maximum and minimum column width from the cells that span only that column.
    //    The minimum is that required by the cell with the largest minimum cell width (or the column 'width', whichever is larger).
    //    The maximum is that required by the cell with the largest maximum cell width (or the column 'width', whichever is larger).
    auto& columns = grid.columnsContext().columns();
    int numberOfRows = grid.rows().size();
    int numberOfColumns = columns.size();
    for (int columnIndex = 0; columnIndex < numberOfColumns; ++columnIndex) {
        auto columnIntrinsicWidths = FormattingContext::IntrinsicWidthConstraints { };
        for (int rowIndex = 0; rowIndex < numberOfRows; ++rowIndex) {
            auto* slot = grid.slot({ columnIndex, rowIndex });
            columnIntrinsicWidths.minimum = std::max(slot->widthConstraints.minimum, columnIntrinsicWidths.minimum);
            columnIntrinsicWidths.maximum = std::max(slot->widthConstraints.maximum, columnIntrinsicWidths.maximum);
        }
        columns[columnIndex].setWidthConstraints(columnIntrinsicWidths);
    }
    // FIXME: Take column group elements into account.
}

LayoutUnit TableFormattingContext::computedTableWidth()
{
    // Column and caption widths influence the final table width as follows:
    // If the 'table' or 'inline-table' element's 'width' property has a computed value (W) other than 'auto', the used width is the greater of
    // W, CAPMIN, and the minimum width required by all the columns plus cell spacing or borders (MIN).
    // If the used width is greater than MIN, the extra width should be distributed over the columns.
    // If the 'table' or 'inline-table' element has 'width: auto', the used width is the greater of the table's containing block width,
    // CAPMIN, and MIN. However, if either CAPMIN or the maximum width required by the columns plus cell spacing or borders (MAX) is
    // less than that of the containing block, use max(MAX, CAPMIN).

    // FIXME: This kind of code usually lives in *FormattingContextGeometry class.
    auto& tableWrapperBox = root();
    auto& style = tableWrapperBox.style();
    auto& containingBlock = *tableWrapperBox.containingBlock();
    auto containingBlockWidth = geometryForBox(containingBlock).contentBoxWidth();

    auto& grid = formattingState().tableGrid();
    auto& columnsContext = grid.columnsContext();
    auto tableWidthConstraints = grid.widthConstraints();

    auto width = geometry().computedValueIfNotAuto(style.width(), containingBlockWidth);
    LayoutUnit usedWidth;
    if (width) {
        if (*width > tableWidthConstraints.minimum) {
            distributeAvailableWidth(*width - tableWidthConstraints.minimum);
            usedWidth = *width;
        } else {
            usedWidth = tableWidthConstraints.minimum;
            useAsContentLogicalWidth(WidthConstraintsType::Minimum);
        }
    } else {
        if (tableWidthConstraints.minimum > containingBlockWidth) {
            usedWidth = tableWidthConstraints.minimum;
            useAsContentLogicalWidth(WidthConstraintsType::Minimum);
        } else if (tableWidthConstraints.maximum < containingBlockWidth) {
            usedWidth = tableWidthConstraints.maximum;
            useAsContentLogicalWidth(WidthConstraintsType::Maximum);
        } else {
            usedWidth = containingBlockWidth;
            distributeAvailableWidth(*width - tableWidthConstraints.minimum);
        }
    }
    // FIXME: This should also deal with collapsing borders etc.
    auto horizontalSpacing = grid.horizontalSpacing();
    auto columnLogicalLeft = horizontalSpacing;
    for (auto& column : columnsContext.columns()) {
        column.setLogicalLeft(columnLogicalLeft);
        columnLogicalLeft += (column.logicalWidth() + horizontalSpacing);
    }
    return usedWidth;
}

void TableFormattingContext::distributeAvailableWidth(LayoutUnit extraHorizontalSpace)
{
    // FIXME: Right now just distribute the extra space equaly among the columns.
    auto& columns = formattingState().tableGrid().columnsContext().columns();
    ASSERT(!columns.isEmpty());

    auto columnExtraSpace = extraHorizontalSpace / columns.size();
    for (auto& column : columns)
        column.setLogicalWidth(column.widthConstraints().minimum + columnExtraSpace);
}

void TableFormattingContext::useAsContentLogicalWidth(WidthConstraintsType type)
{
    auto& columns = formattingState().tableGrid().columnsContext().columns();
    ASSERT(!columns.isEmpty());

    for (auto& column : columns)
        column.setLogicalWidth(type == WidthConstraintsType::Minimum ? column.widthConstraints().minimum : column.widthConstraints().maximum);
}

}
}

#endif
