/*
 * 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.left(), box.top(), box.width(), box.height() };
    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)
