/*
 * Copyright (C) 2020 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 "DisplayTreeBuilder.h"

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

#include "DisplayBoxFactory.h"
#include "DisplayContainerBox.h"
#include "DisplayStackingItem.h"
#include "DisplayStyle.h"
#include "DisplayTree.h"
#include "InlineFormattingState.h"
#include "LayoutBoxGeometry.h"
#include "LayoutChildIterator.h"
#include "LayoutContainerBox.h"
#include "LayoutReplacedBox.h"
#include "LayoutState.h"
#include "LayoutTreeBuilder.h" // Just for showLayoutTree.
#include "Logging.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/text/TextStream.h>

namespace WebCore {
namespace Display {

class PositioningContext {
public:
    PositioningContext(const Display::ContainerBox& rootDisplayBox)
        : m_fixedPositionContainer({ rootDisplayBox, { } })
        , m_absolutePositionContainer({ rootDisplayBox, { } })
        , m_inFlowContainer ({ rootDisplayBox, { } })
    {
    }

    PositioningContext contextForDescendants(const Layout::Box& layoutBox, const Layout::BoxGeometry geometry, const Display::ContainerBox& displayBox) const
    {
        auto currentOffset = containingBlockContextForLayoutBox(layoutBox).offsetFromRoot;

        auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(geometry) };
        currentOffset += toLayoutSize(borderBoxRect.location());

        auto currentBoxes = ContainingBlockContext { displayBox, currentOffset };
        return {
            layoutBox.isContainingBlockForFixedPosition() ? currentBoxes : m_fixedPositionContainer,
            layoutBox.isContainingBlockForOutOfFlowPosition() ? currentBoxes : m_absolutePositionContainer,
            layoutBox.isContainingBlockForInFlow() ? currentBoxes : m_inFlowContainer
        };
    }

    const ContainingBlockContext& containingBlockContextForLayoutBox(const Layout::Box& layoutBox) const
    {
        if (layoutBox.isFixedPositioned())
            return m_fixedPositionContainer;

        if (layoutBox.isOutOfFlowPositioned())
            return m_absolutePositionContainer;

        return m_inFlowContainer;
    }
    
    const ContainingBlockContext& inFlowContainingBlockContext() const { return m_inFlowContainer; }

private:
    PositioningContext(const ContainingBlockContext& fixedContainer, const ContainingBlockContext& absoluteContainer, const ContainingBlockContext& inFlowContainer)
        : m_fixedPositionContainer(fixedContainer)
        , m_absolutePositionContainer(absoluteContainer)
        , m_inFlowContainer(inFlowContainer)
    {
    }

    ContainingBlockContext m_fixedPositionContainer;
    ContainingBlockContext m_absolutePositionContainer;
    ContainingBlockContext m_inFlowContainer;
};

struct BuildingState {
    const ContainerBox& inFlowContainingBlockBox() const { return positioningContext.inFlowContainingBlockContext().box; }

    PositioningContext positioningContext;
    StackingItem& currentStackingItem;
    StackingItem& currentStackingContextItem;

    UnadjustedAbsoluteFloatRect currentStackingItemPaintedContentExtent; // This stacking item's contents only.
    UnadjustedAbsoluteFloatRect currentStackingItemPaintingExtent; // Including descendant items.
};

TreeBuilder::TreeBuilder(float pixelSnappingFactor)
    : m_boxFactory(*this, pixelSnappingFactor)
    , m_stateStack(makeUnique<Vector<BuildingState>>())
{
    m_stateStack->reserveInitialCapacity(32);
}

TreeBuilder::~TreeBuilder() = default;

std::unique_ptr<Tree> TreeBuilder::build(const Layout::LayoutState& layoutState)
{
    auto& rootLayoutBox = layoutState.root();

#if ENABLE(TREE_DEBUGGING)
    LOG_WITH_STREAM(FormattingContextLayout, stream << "Building display tree for:\n" << layoutTreeAsText(rootLayoutBox, &layoutState));
#endif

    ASSERT(!m_tree);
    m_tree = makeUnique<Tree>();

    m_rootBackgroundPropgation = BoxFactory::determineRootBackgroundPropagation(rootLayoutBox);

    auto geometry = layoutState.geometryForBox(rootLayoutBox);
    auto rootDisplayBox = m_boxFactory.displayBoxForRootBox(rootLayoutBox, geometry, m_rootBackgroundPropgation);

    auto insertionPosition = InsertionPosition { *rootDisplayBox };
    auto rootStackingItem = makeUnique<StackingItem>(WTFMove(rootDisplayBox));

    if (rootLayoutBox.firstChild()) {
        auto& rootContainerBox = downcast<ContainerBox>(rootStackingItem->box());
        m_stateStack->append({ { rootContainerBox }, *rootStackingItem, *rootStackingItem, { }, { } });
        recursiveBuildDisplayTree(layoutState, *rootLayoutBox.firstChild(), insertionPosition);
    }

#if ENABLE(TREE_DEBUGGING)
    LOG_WITH_STREAM(FormattingContextLayout, stream << "Display tree:\n" << displayTreeAsText(*rootStackingItem));
#endif
    m_tree->setRootStackingItem(WTFMove(rootStackingItem));
    return WTFMove(m_tree);
}

void TreeBuilder::pushStateForBoxDescendants(const Layout::ContainerBox& layoutContainerBox, const Layout::BoxGeometry& layoutGeometry, const ContainerBox& displayBox, StackingItem* boxStackingItem)
{
    auto& positioningContext = m_stateStack->last().positioningContext;

    auto currentStackingItem = [&]() -> StackingItem& {
        if (boxStackingItem)
            return *boxStackingItem;

        return m_stateStack->last().currentStackingItem;
    };

    auto currentStackingContextItem = [&]() -> StackingItem& {
        if (boxStackingItem && boxStackingItem->isStackingContext())
            return *boxStackingItem;
        
        return m_stateStack->last().currentStackingContextItem;
    };

    m_stateStack->append({
        positioningContext.contextForDescendants(layoutContainerBox, layoutGeometry, displayBox),
        currentStackingItem(),
        currentStackingContextItem(),
        { },
        { }
    });
}

void TreeBuilder::popState(const BoxModelBox& currentBox)
{
    ASSERT(m_stateStack->size() > 1);
    auto& currentState = m_stateStack->last();
    auto& previousState = m_stateStack->at(m_stateStack->size() - 2);

    bool endingStackingItem = &currentState.currentStackingItem.box() == &currentBox;
    bool endingStackingContextItem = &currentState.currentStackingContextItem.box() == &currentBox;

    // We've accumulated into currentStackingItemPaintedContentExtent while building descendant boxes.
    auto paintedContentExtent = currentState.currentStackingItemPaintedContentExtent;

    // Often, but not always, containingBlockBox will be currentBox. If it has overflow clipping, clip the rect from descendants.
    auto& containingBlockBox = currentState.inFlowContainingBlockBox();
    if (containingBlockBox.style().hasClippedOverflow()) {
        auto clipRect = containingBlockBox.absolutePaddingBoxRect();
        paintedContentExtent.intersect(clipRect);
    }

    // Now union with this box's extent (which is outside the clip).
    auto boxPaintingExtent = unionRect(paintedContentExtent, currentBox.absolutePaintingExtent());

    if (endingStackingItem) {
        currentState.currentStackingItem.setPaintedContentBounds(boxPaintingExtent);
        
        // Now accumulate this item's extent (possibly clipped) into that of its parent item.
        auto descendantItemsPaintingExtent = currentState.currentStackingItemPaintingExtent;

        if (containingBlockBox.style().hasClippedOverflow()) {
            auto clipRect = containingBlockBox.absolutePaddingBoxRect();
            descendantItemsPaintingExtent.intersect(clipRect);
        }

        auto itemPaintingExtent = unionRect(descendantItemsPaintingExtent, boxPaintingExtent);
        currentState.currentStackingItem.setPaintedBoundsIncludingDescendantItems(itemPaintingExtent);

        previousState.currentStackingItemPaintingExtent.unite(itemPaintingExtent);
    } else
        previousState.currentStackingItemPaintedContentExtent.unite(boxPaintingExtent);

    if (endingStackingContextItem)
        currentState.currentStackingContextItem.sortLists();

    m_stateStack->removeLast();
}

void TreeBuilder::didAppendNonContainerStackingItem(StackingItem& item)
{
    // This is s simplified version of pushStateForBoxDescendants/popState.
    auto currentStackingContextItem = [&]() -> StackingItem& {
        if (item.isStackingContext())
            return item;
        
        return m_stateStack->last().currentStackingContextItem;
    };

    m_stateStack->append({
        m_stateStack->last().positioningContext,
        item,
        currentStackingContextItem(),
        { },
        { }
    });

    popState(item.box());
}

void TreeBuilder::accountForBoxPaintingExtent(const Box& box)
{
    // FIXME: Need to account for transforms.
    currentState().currentStackingItemPaintedContentExtent.unite(box.absolutePaintingExtent());
}

BuildingState& TreeBuilder::currentState()
{
    ASSERT(m_stateStack && m_stateStack->size());
    return m_stateStack->last();
}

const PositioningContext& TreeBuilder::positioningContext()
{
    return currentState().positioningContext;
}

void TreeBuilder::insert(std::unique_ptr<Box>&& box, InsertionPosition& insertionPosition) const
{
    box->setParent(&insertionPosition.container);
    if (insertionPosition.currentChild) {
        auto boxPtr = box.get();
        insertionPosition.currentChild->setNextSibling(WTFMove(box));
        insertionPosition.currentChild = boxPtr;
    } else {
        insertionPosition.currentChild = box.get();
        insertionPosition.container.setFirstChild(WTFMove(box));
    }
}

StackingItem* TreeBuilder::insertIntoTree(std::unique_ptr<Box>&& box, InsertionPosition& insertionPosition, WillTraverseDescendants willTraverseDescendants)
{
    if (box->participatesInZOrderSorting() && is<BoxModelBox>(*box)) {
        auto boxModelBox = std::unique_ptr<BoxModelBox> { downcast<BoxModelBox>(box.release()) };
        auto stackingItem = makeUnique<StackingItem>(WTFMove(boxModelBox));

        // This painted bounds will get extended as we traverse box descendants.
        stackingItem->setPaintedContentBounds(stackingItem->box().absolutePaintingExtent());

        auto* stackingItemPtr = stackingItem.get();
        currentState().currentStackingContextItem.addChildStackingItem(WTFMove(stackingItem));
        
        if (willTraverseDescendants == WillTraverseDescendants::No)
            didAppendNonContainerStackingItem(*stackingItemPtr);

        return stackingItemPtr;
    }

    insert(WTFMove(box), insertionPosition);

    if (willTraverseDescendants == WillTraverseDescendants::No)
        accountForBoxPaintingExtent(*insertionPosition.currentChild);

    return nullptr;
}

void TreeBuilder::buildInlineDisplayTree(const Layout::LayoutState& layoutState, const Layout::ContainerBox& inlineFormattingRoot, InsertionPosition& insertionPosition)
{
    auto& inlineFormattingState = layoutState.formattingStateForInlineFormattingContext(inlineFormattingRoot);

    for (auto& box : inlineFormattingState.boxes()) {
        if (box.isRootInlineBox()) {
            // Not supported yet.
            continue;
        }

        if (box.text()) {
            auto& lineGeometry = inlineFormattingState.lines().at(box.lineIndex());
            auto textBox = m_boxFactory.displayBoxForTextRun(box, lineGeometry, positioningContext().inFlowContainingBlockContext());
            insert(WTFMove(textBox), insertionPosition);
            accountForBoxPaintingExtent(*insertionPosition.currentChild);
            continue;
        }

        if (is<Layout::ContainerBox>(box.layoutBox())) {
            recursiveBuildDisplayTree(layoutState, box.layoutBox(), insertionPosition);
            continue;
        }

        // FIXME: Workaround for webkit.orgb/b/219335.
        if (box.layoutBox().isLineBreakBox() && box.layoutBox().isOutOfFlowPositioned())
            continue;

        auto geometry = layoutState.geometryForBox(box.layoutBox());
        auto displayBox = m_boxFactory.displayBoxForLayoutBox(box.layoutBox(), geometry, positioningContext().inFlowContainingBlockContext());
        insertIntoTree(WTFMove(displayBox), insertionPosition, WillTraverseDescendants::No);
    }
}

void TreeBuilder::recursiveBuildDisplayTree(const Layout::LayoutState& layoutState, const Layout::Box& layoutBox, InsertionPosition& insertionPosition)
{
    auto geometry = layoutState.geometryForBox(layoutBox);
    std::unique_ptr<Box> displayBox;

    auto& containingBlockContext = positioningContext().containingBlockContextForLayoutBox(layoutBox);
    if (layoutBox.isBodyBox())
        displayBox = m_boxFactory.displayBoxForBodyBox(layoutBox, geometry, containingBlockContext, m_rootBackgroundPropgation);
    else
        displayBox = m_boxFactory.displayBoxForLayoutBox(layoutBox, geometry, containingBlockContext);

    Box& currentBox = *displayBox;

    auto willTraverseDescendants = (is<Layout::ContainerBox>(layoutBox) && downcast<Layout::ContainerBox>(layoutBox).hasChild()) ? WillTraverseDescendants::Yes : WillTraverseDescendants::No;
    auto* stackingItem = insertIntoTree(WTFMove(displayBox), insertionPosition, willTraverseDescendants);
    if (willTraverseDescendants == WillTraverseDescendants::No)
        return;

    auto& layoutContainerBox = downcast<Layout::ContainerBox>(layoutBox);

    ContainerBox& currentContainerBox = downcast<ContainerBox>(currentBox);
    pushStateForBoxDescendants(layoutContainerBox, geometry, currentContainerBox, stackingItem);

    auto insertionPositionForChildren = InsertionPosition { currentContainerBox };

    enum class DescendantBoxInclusion { AllBoxes, OutOfFlowOnly };
    auto boxInclusion = DescendantBoxInclusion::AllBoxes;

    if (layoutContainerBox.establishesInlineFormattingContext()) {
        buildInlineDisplayTree(layoutState, downcast<Layout::ContainerBox>(layoutContainerBox), insertionPositionForChildren);
        boxInclusion = DescendantBoxInclusion::OutOfFlowOnly;
    }

    auto includeBox = [](DescendantBoxInclusion boxInclusion, const Layout::Box& box) {
        switch (boxInclusion) {
        case DescendantBoxInclusion::AllBoxes: return true;
        case DescendantBoxInclusion::OutOfFlowOnly: return !box.isInFlow();
        }
        return false;
    };

    for (auto& child : Layout::childrenOfType<Layout::Box>(layoutContainerBox)) {
        if (includeBox(boxInclusion, child) && layoutState.hasBoxGeometry(child))
            recursiveBuildDisplayTree(layoutState, child, insertionPositionForChildren);
    }

    popState(currentContainerBox);
}

#if ENABLE(TREE_DEBUGGING)

static void outputDisplayBox(TextStream& stream, const Box& displayBox, bool writeIndent = true)
{
    if (writeIndent)
        stream.writeIndent();

    stream << displayBox.debugDescription();
    stream << "\n";
}

static void outputDisplayTree(TextStream& stream, const Box& displayBox, bool writeFirstItemIndent = true)
{
    outputDisplayBox(stream, displayBox, writeFirstItemIndent);

    if (is<ContainerBox>(displayBox)) {
        TextStream::IndentScope indent(stream);
        for (auto child = downcast<ContainerBox>(displayBox).firstChild(); child; child = child->nextSibling())
            outputDisplayTree(stream, *child);
    }
}

String displayTreeAsText(const Box& box)
{
    TextStream stream(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
    outputDisplayTree(stream, box);
    return stream.release();
}

void showDisplayTree(const Box& box)
{
    auto treeAsText = displayTreeAsText(box);
    WTFLogAlways("%s", treeAsText.utf8().data());
}

static void outputStackingTree(TextStream& stream, const char* prefix, const StackingItem& stackingItem)
{
    stream.writeIndent();
    stream << "[" << prefix << "] item (" << &stackingItem << ") " << stackingItem.paintedContentBounds() << " - ";

    TextStream::IndentScope indent(stream);
    outputDisplayTree(stream, stackingItem.box(), false);

    {
        TextStream::IndentScope indent(stream);
        for (auto& childStackingItem : stackingItem.negativeZOrderList())
            outputStackingTree(stream, "-", *childStackingItem);

        for (auto& childStackingItem : stackingItem.positiveZOrderList())
            outputStackingTree(stream, childStackingItem->isStackingContext() ? "+" : "p", *childStackingItem);
    }
}

String displayTreeAsText(const StackingItem& stackingItem)
{
    TextStream stream(TextStream::LineMode::MultipleLine);
    outputStackingTree(stream, "+", stackingItem);
    return stream.release();
}

void showDisplayTree(const StackingItem& stackingItem)
{
    auto treeAsText = displayTreeAsText(stackingItem);
    WTFLogAlways("%s", treeAsText.utf8().data());
}

#endif

} // namespace Display
} // namespace WebCore

#endif // ENABLE(LAYOUT_FORMATTING_CONTEXT)
