/*
 * 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 "DisplayBoxFactory.h"

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

#include "DisplayBoxClip.h"
#include "DisplayBoxDecorationData.h"
#include "DisplayBoxDecorationPainter.h"
#include "DisplayBoxRareGeometry.h"
#include "DisplayContainerBox.h"
#include "DisplayFillLayerImageGeometry.h"
#include "DisplayImageBox.h"
#include "DisplayTextBox.h"
#include "DisplayTree.h"
#include "DisplayTreeBuilder.h"
#include "FloatPoint3D.h"
#include "InlineDisplayLine.h"
#include "LayoutBoxGeometry.h"
#include "LayoutContainerBox.h"
#include "LayoutInitialContainingBlock.h"
#include "LayoutReplacedBox.h"
#include "Logging.h"
#include "TransformationMatrix.h"

namespace WebCore {
namespace Display {

BoxFactory::BoxFactory(TreeBuilder& builder, float pixelSnappingFactor)
    : m_treeBuilder(builder)
    , m_pixelSnappingFactor(pixelSnappingFactor)
{
}

RootBackgroundPropagation BoxFactory::determineRootBackgroundPropagation(const Layout::ContainerBox& rootLayoutBox)
{
    auto* documentElementBox = documentElementBoxFromRootBox(rootLayoutBox);
    auto* bodyBox = bodyBoxFromRootBox(rootLayoutBox);

    if (documentElementBox && documentElementBox->style().hasBackground())
        return RootBackgroundPropagation::None;

    if (bodyBox && bodyBox->style().hasBackground())
        return RootBackgroundPropagation::BodyToRoot;
    
    return RootBackgroundPropagation::None;
}

std::unique_ptr<ContainerBox> BoxFactory::displayBoxForRootBox(const Layout::ContainerBox& rootLayoutBox, const Layout::BoxGeometry& geometry, RootBackgroundPropagation rootBackgroundPropagation) const
{
    ASSERT(is<Layout::InitialContainingBlock>(rootLayoutBox));

    // FIXME: Need to do logical -> physical coordinate mapping here.
    auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(geometry) };

    auto* documentElementBox = documentElementBoxFromRootBox(rootLayoutBox);

    const RenderStyle* styleForBackground = documentElementBox ? &documentElementBox->style() : nullptr;

    if (rootBackgroundPropagation == RootBackgroundPropagation::BodyToRoot) {
        if (auto* bodyBox = bodyBoxFromRootBox(rootLayoutBox))
            styleForBackground = &bodyBox->style();
    }

    auto style = Style { rootLayoutBox.style(), styleForBackground };

    auto rootBox = makeUnique<ContainerBox>(m_treeBuilder.tree(), UnadjustedAbsoluteFloatRect { snapRectToDevicePixels(borderBoxRect, m_pixelSnappingFactor) }, WTFMove(style));
    // We pass rootBox as its own containingBlockBox here to allow it to be a reference everywhere else.
    setupBoxModelBox(*rootBox, rootLayoutBox, geometry, { *rootBox, { 0, 0 } }, styleForBackground);
    return rootBox;
}

std::unique_ptr<Box> BoxFactory::displayBoxForBodyBox(const Layout::Box& layoutBox, const Layout::BoxGeometry& geometry, const ContainingBlockContext& containingBlockContext, RootBackgroundPropagation rootBackgroundPropagation) const
{
    const RenderStyle* styleForBackground = &layoutBox.style();
    
    if (rootBackgroundPropagation == RootBackgroundPropagation::BodyToRoot)
        styleForBackground = nullptr;
    
    auto style = Style { layoutBox.style(), styleForBackground };
    return displayBoxForLayoutBox(layoutBox, geometry, containingBlockContext, styleForBackground, WTFMove(style));
}

std::unique_ptr<Box> BoxFactory::displayBoxForLayoutBox(const Layout::Box& layoutBox, const Layout::BoxGeometry& geometry, const ContainingBlockContext& containingBlockContext) const
{
    auto style = Style { layoutBox.style() };
    return displayBoxForLayoutBox(layoutBox, geometry, containingBlockContext, &layoutBox.style(), WTFMove(style));
}

std::unique_ptr<Box> BoxFactory::displayBoxForLayoutBox(const Layout::Box& layoutBox, const Layout::BoxGeometry& geometry, const ContainingBlockContext& containingBlockContext, const RenderStyle* styleForBackground, Style&& style) const
{
    // FIXME: Need to map logical to physical rects.
    auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(geometry) };
    borderBoxRect.move(containingBlockContext.offsetFromRoot);
    auto pixelSnappedBorderBoxRect = UnadjustedAbsoluteFloatRect { snapRectToDevicePixels(borderBoxRect, m_pixelSnappingFactor) };

    // FIXME: Handle isAnonymous()
    
    if (is<Layout::ReplacedBox>(layoutBox)) {
        // FIXME: Don't assume it's an image.
        CachedResourceHandle<CachedImage> cachedImageHandle = downcast<Layout::ReplacedBox>(layoutBox).cachedImage();
        auto imageBox = makeUnique<ImageBox>(m_treeBuilder.tree(), pixelSnappedBorderBoxRect, WTFMove(style), WTFMove(cachedImageHandle));
        setupBoxModelBox(*imageBox, layoutBox, geometry, containingBlockContext, styleForBackground);
        return imageBox;
    }
    
    if (is<Layout::ContainerBox>(layoutBox)) {
        // FIXME: The decision to make a ContainerBox should be made based on whether this Display::Box will have children.
        auto containerBox = makeUnique<ContainerBox>(m_treeBuilder.tree(), pixelSnappedBorderBoxRect, WTFMove(style));
        setupBoxModelBox(*containerBox, layoutBox, geometry, containingBlockContext, styleForBackground);
        return containerBox;
    }

    OptionSet<Box::TypeFlags> flags;
    // FIXME: Workaround for webkit.org/b/219335.
    if (layoutBox.isLineBreakBox())
        flags.add(Box::TypeFlags::LineBreakBox);

    return makeUnique<Box>(m_treeBuilder.tree(), pixelSnappedBorderBoxRect, WTFMove(style), flags);
}

std::unique_ptr<Box> BoxFactory::displayBoxForTextRun(const InlineDisplay::Box& box, const InlineDisplay::Line& line, const ContainingBlockContext& containingBlockContext) const
{
    UNUSED_PARAM(line);
    ASSERT(box.text());

    auto boxRect = LayoutRect { box.logicalLeft(), box.logicalTop(), box.logicalWidth(), box.logicalHeight() };
    boxRect.move(containingBlockContext.offsetFromRoot);

    auto style = Style { box.layoutBox().style() };
    return makeUnique<TextBox>(m_treeBuilder.tree(), UnadjustedAbsoluteFloatRect { snapRectToDevicePixels(boxRect, m_pixelSnappingFactor) }, WTFMove(style), box);
}

void BoxFactory::setupBoxGeometry(BoxModelBox& box, const Layout::Box&, const Layout::BoxGeometry& layoutGeometry, const ContainingBlockContext& containingBlockContext) const
{
    auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(layoutGeometry) };
    borderBoxRect.move(containingBlockContext.offsetFromRoot);

    auto paddingBoxRect = LayoutRect { layoutGeometry.paddingBox() };
    paddingBoxRect.moveBy(borderBoxRect.location());
    box.setAbsolutePaddingBoxRect(UnadjustedAbsoluteFloatRect { snapRectToDevicePixels(paddingBoxRect, m_pixelSnappingFactor) });

    auto contentBoxRect = LayoutRect { layoutGeometry.contentBox() };
    contentBoxRect.moveBy(borderBoxRect.location());
    box.setAbsoluteContentBoxRect(UnadjustedAbsoluteFloatRect { snapRectToDevicePixels(contentBoxRect, m_pixelSnappingFactor) });

    if (is<ReplacedBox>(box)) {
        auto& replacedBox = downcast<ReplacedBox>(box);
        // FIXME: Need to get the correct rect taking object-fit etc into account.
        auto replacedContentRect = LayoutRect { layoutGeometry.contentBoxLeft(), layoutGeometry.contentBoxTop(), layoutGeometry.contentBoxWidth(), layoutGeometry.contentBoxHeight() };
        replacedContentRect.moveBy(borderBoxRect.location());
        auto pixelSnappedReplacedContentRect = UnadjustedAbsoluteFloatRect { snapRectToDevicePixels(replacedContentRect, m_pixelSnappingFactor) };
        replacedBox.setReplacedContentRect(pixelSnappedReplacedContentRect);
    }
}

std::unique_ptr<BoxDecorationData> BoxFactory::constructBoxDecorationData(const Layout::Box& layoutBox, const Layout::BoxGeometry& layoutGeometry, const RenderStyle* styleForBackground, LayoutSize offsetFromRoot) const
{
    auto boxDecorationData = makeUnique<BoxDecorationData>();

    if (styleForBackground) {
        auto backgroundImageGeometry = calculateFillLayerImageGeometry(*styleForBackground, layoutGeometry, offsetFromRoot, m_pixelSnappingFactor);
        boxDecorationData->setBackgroundImageGeometry(WTFMove(backgroundImageGeometry));
    }

    bool includeLogicalLeftEdge = true; // FIXME.
    bool includeLogicalRightEdge = true; // FIXME.
    auto borderEdges = calculateBorderEdges(layoutBox.style(), m_pixelSnappingFactor, includeLogicalLeftEdge, includeLogicalRightEdge);
    boxDecorationData->setBorderEdges(WTFMove(borderEdges));

    return boxDecorationData;
}

FloatPoint3D BoxFactory::computeTransformOrigin(const BoxModelBox& box, const Layout::BoxGeometry& layoutGeometry, const RenderStyle& renderStyle, LayoutSize offsetFromRoot) const
{
    auto transformBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(layoutGeometry) };

    auto absoluteOrigin = LayoutPoint {
        offsetFromRoot.width() + transformBoxRect.x() + valueForLength(renderStyle.transformOriginX(), transformBoxRect.width()),
        offsetFromRoot.height() + transformBoxRect.y() + valueForLength(renderStyle.transformOriginY(), transformBoxRect.height())
    };

    auto snappedAbsoluteOrigin = roundPointToDevicePixels(absoluteOrigin, m_pixelSnappingFactor);
    auto boxRelativeTransformOriginXY = snappedAbsoluteOrigin - box.absoluteBorderBoxRect().location();

    return { boxRelativeTransformOriginXY.width(), boxRelativeTransformOriginXY.height(), renderStyle.transformOriginZ() };
}

TransformationMatrix BoxFactory::computeTransformationMatrix(const BoxModelBox& box, const Layout::BoxGeometry& layoutGeometry, const RenderStyle& renderStyle, LayoutSize offsetFromRoot) const
{
    auto boxRelativeTransformOrigin = computeTransformOrigin(box, layoutGeometry, renderStyle, offsetFromRoot);

    // FIXME: Respect transform-box.
    auto transformBoxRect = box.absoluteBorderBoxRect();

    // FIXME: This is similar to RenderStyle::applyTransform(), but that fails to pixel snap transform origin.
    auto transform = TransformationMatrix { };
    transform.translate3d(boxRelativeTransformOrigin.x(), boxRelativeTransformOrigin.y(), boxRelativeTransformOrigin.z());

    for (auto& operation : renderStyle.transform().operations())
        operation->apply(transform, transformBoxRect.size());

    transform.translate3d(-boxRelativeTransformOrigin.x(), -boxRelativeTransformOrigin.y(), -boxRelativeTransformOrigin.z());
    return transform;

}

std::unique_ptr<BoxRareGeometry> BoxFactory::constructBoxRareGeometry(const BoxModelBox& box, const Layout::Box& layoutBox, const Layout::BoxGeometry& layoutGeometry, LayoutSize offsetFromRoot) const
{
    auto& renderStyle = layoutBox.style();

    if (!box.style().hasTransform() && !renderStyle.hasBorderRadius())
        return nullptr;

    auto boxRareGeometry = makeUnique<BoxRareGeometry>();

    if (renderStyle.hasBorderRadius()) {
        bool includeLogicalLeftEdge = true; // FIXME.
        bool includeLogicalRightEdge = true; // FIXME.

        auto borderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(layoutGeometry) };
        auto borderRoundedRect = renderStyle.getRoundedBorderFor(borderBoxRect, includeLogicalLeftEdge, includeLogicalRightEdge);
        auto snappedRoundedRect = borderRoundedRect.pixelSnappedRoundedRectForPainting(m_pixelSnappingFactor);

        auto borderRadii = makeUnique<FloatRoundedRect::Radii>(snappedRoundedRect.radii());
        boxRareGeometry->setBorderRadii(WTFMove(borderRadii));
    }

    if (box.style().hasTransform()) {
        auto transformationMatrix = computeTransformationMatrix(box, layoutGeometry, layoutBox.style(), offsetFromRoot);
        boxRareGeometry->setTransform(WTFMove(transformationMatrix));
    }

    return boxRareGeometry;
}

void BoxFactory::setupBoxModelBox(BoxModelBox& box, const Layout::Box& layoutBox, const Layout::BoxGeometry& layoutGeometry, const ContainingBlockContext& containingBlockContext, const RenderStyle* styleForBackground) const
{
    setupBoxGeometry(box, layoutBox, layoutGeometry, containingBlockContext);

    auto boxRareGeometry = constructBoxRareGeometry(box, layoutBox, layoutGeometry, containingBlockContext.offsetFromRoot);
    box.setBoxRareGeometry(WTFMove(boxRareGeometry));

    box.setHasTransform(box.style().hasTransform());

    auto& renderStyle = layoutBox.style();
    if (!(styleForBackground && styleForBackground->hasBackground()) && !renderStyle.hasBorder()) // FIXME: Misses border-radius.
        return;

    auto boxDecorationData = constructBoxDecorationData(layoutBox, layoutGeometry, styleForBackground, containingBlockContext.offsetFromRoot);
    box.setBoxDecorationData(WTFMove(boxDecorationData));

    if (box.participatesInZOrderSorting()) {
        RefPtr<BoxClip> clip = containingBlockContext.box.clipForDescendants();
        box.setAncestorClip(WTFMove(clip));
    }
}

const Layout::ContainerBox* BoxFactory::documentElementBoxFromRootBox(const Layout::ContainerBox& rootLayoutBox)
{
    auto* documentBox = rootLayoutBox.firstChild();
    if (!documentBox || !documentBox->isDocumentBox() || !is<Layout::ContainerBox>(documentBox))
        return nullptr;

    return downcast<Layout::ContainerBox>(documentBox);
}

const Layout::Box* BoxFactory::bodyBoxFromRootBox(const Layout::ContainerBox& rootLayoutBox)
{
    auto* documentBox = rootLayoutBox.firstChild();
    if (!documentBox || !documentBox->isDocumentBox() || !is<Layout::ContainerBox>(documentBox))
        return nullptr;

    auto* bodyBox = downcast<Layout::ContainerBox>(documentBox)->firstChild();
    if (!bodyBox || !bodyBox->isBodyBox())
        return nullptr;

    return bodyBox;
}

} // namespace Display
} // namespace WebCore

#endif // ENABLE(LAYOUT_FORMATTING_CONTEXT)
