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

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

#ifndef NDEBUG
#include "BlockFormattingState.h"
#include "InlineFormattingState.h"
#include "LayoutBox.h"
#include "LayoutBoxGeometry.h"
#include "LayoutContainerBox.h"
#include "LayoutContext.h"
#include "LayoutTreeBuilder.h"
#include "LegacyInlineTextBox.h"
#include "RenderBox.h"
#include "RenderInline.h"
#include "RenderLineBreak.h"
#include "RenderTableCell.h"
#include "RenderTableSection.h"
#include "RenderView.h"
#include <wtf/text/TextStream.h>

namespace WebCore {
namespace Layout {

static bool areEssentiallyEqual(LayoutUnit a, LayoutUnit b)
{
    if (a == b)
        return true;
    // 1/4th CSS pixel.
    constexpr float epsilon = kFixedPointDenominator / 4;
    return abs(a.rawValue() - b.rawValue()) <= epsilon;
}

static bool areEssentiallyEqual(float a, InlineLayoutUnit b)
{
    return areEssentiallyEqual(LayoutUnit { a }, LayoutUnit { b });
}

static bool areEssentiallyEqual(LayoutRect a, LayoutRect b)
{
    return areEssentiallyEqual(a.x(), b.x())
        && areEssentiallyEqual(a.y(), b.y())
        && areEssentiallyEqual(a.width(), b.width())
        && areEssentiallyEqual(a.height(), b.height());
}

static bool checkForMatchingNonTextRuns(const InlineDisplay::Box& box, const WebCore::LegacyInlineBox& inlineBox)
{
    return areEssentiallyEqual(inlineBox.left(), box.left())
        && areEssentiallyEqual(inlineBox.right(), box.right())
        && areEssentiallyEqual(inlineBox.top(), box.top())
        && areEssentiallyEqual(inlineBox.bottom(), box.bottom());
}


static bool checkForMatchingTextRuns(InlineDisplay::Box& box, const WebCore::LegacyInlineTextBox& inlineTextBox)
{
    if (!box.text())
        return false;
    return areEssentiallyEqual(inlineTextBox.left(), box.left())
        && areEssentiallyEqual(inlineTextBox.right(), box.right())
        && areEssentiallyEqual(inlineTextBox.top(), box.top())
        && areEssentiallyEqual(inlineTextBox.bottom(), box.bottom())
        && (inlineTextBox.isLineBreak() || (inlineTextBox.start() == box.text()->start() && inlineTextBox.end() == box.text()->end()));
}

static void collectFlowBoxSubtree(const LegacyInlineFlowBox& flowbox, Vector<WebCore::LegacyInlineBox*>& inlineBoxes)
{
    auto* inlineBox = flowbox.firstLeafDescendant();
    auto* lastLeafDescendant = flowbox.lastLeafDescendant();
    while (inlineBox) {
        inlineBoxes.append(inlineBox);
        if (inlineBox == lastLeafDescendant)
            break;
        inlineBox = inlineBox->nextLeafOnLine();
    }
}

static void collectInlineBoxes(const RenderBlockFlow& root, Vector<WebCore::LegacyInlineBox*>& inlineBoxes)
{
    for (auto* rootLine = root.firstRootBox(); rootLine; rootLine = rootLine->nextRootBox()) {
        for (auto* inlineBox = rootLine->firstChild(); inlineBox; inlineBox = inlineBox->nextOnLine()) {
            if (!is<LegacyInlineFlowBox>(inlineBox)) {
                inlineBoxes.append(inlineBox);
                continue;
            }
            collectFlowBoxSubtree(downcast<LegacyInlineFlowBox>(*inlineBox), inlineBoxes);
        }
    }
}

static bool outputMismatchingComplexLineInformationIfNeeded(TextStream& stream, const LayoutState& layoutState, const RenderBlockFlow& blockFlow, const ContainerBox& inlineFormattingRoot)
{
    auto& inlineFormattingState = layoutState.formattingStateForFormattingContext(inlineFormattingRoot);
    auto& boxes = downcast<InlineFormattingState>(inlineFormattingState).boxes();
    // Collect inlineboxes.
    Vector<WebCore::LegacyInlineBox*> inlineBoxes;
    collectInlineBoxes(blockFlow, inlineBoxes);

    auto mismatched = false;
    unsigned boxIndex = 0;

    if (inlineBoxes.size() != boxes.size()) {
        stream << "Warning: mismatching number of boxes: inlineboxes(" << inlineBoxes.size() << ") vs. inline boxes(" << boxes.size() << ")";
        stream.nextLine();
    }

    for (unsigned inlineBoxIndex = 0; inlineBoxIndex < inlineBoxes.size() && boxIndex < boxes.size(); ++inlineBoxIndex) {
        auto& box = boxes[boxIndex];
        auto* inlineBox = inlineBoxes[inlineBoxIndex];
        auto* inlineTextBox = dynamicDowncast<WebCore::LegacyInlineTextBox>(inlineBox);
        bool matchingRuns = inlineTextBox ? checkForMatchingTextRuns(box, *inlineTextBox) : checkForMatchingNonTextRuns(box, *inlineBox);

        if (!matchingRuns) {
            
            if (is<RenderLineBreak>(inlineBox->renderer())) {
                // <br> positioning is weird at this point. It needs proper baseline.
                matchingRuns = true;
                ++boxIndex;
                continue;
            }

            stream << "Mismatching: box";

            if (inlineTextBox)
                stream << " (" << inlineTextBox->start() << ", " << inlineTextBox->end() << ")";
            stream << " (" << inlineBox->logicalLeft() << ", " << inlineBox->logicalTop() << ") (" << inlineBox->logicalWidth() << "x" << inlineBox->logicalHeight() << ")";

            stream << " inline box";
            if (box.text())
                stream << " (" << box.text()->start() << ", " << box.text()->end() << ")";
            stream << " (" << box.left() << ", " << box.top() << ") (" << box.width() << "x" << box.height() << ")";
            stream.nextLine();
            mismatched = true;
        }
        ++boxIndex;
    }
    return mismatched;
}

static bool outputMismatchingBlockBoxInformationIfNeeded(TextStream& stream, const LayoutState& layoutState, const RenderBox& renderer, const Box& layoutBox)
{
    bool firstMismatchingRect = true;
    auto outputRect = [&] (const String& prefix, const LayoutRect& rendererRect, const LayoutRect& layoutRect) {
        if (firstMismatchingRect) {
            stream << (renderer.element() ? renderer.element()->nodeName().utf8().data() : "") << " " << renderer.renderName() << "(" << &renderer << ") layoutBox(" << &layoutBox << ")";
            stream.nextLine();
            firstMismatchingRect = false;
        }

        stream  << prefix.utf8().data() << "\trenderer->(" << rendererRect.x() << "," << rendererRect.y() << ") (" << rendererRect.width() << "x" << rendererRect.height() << ")"
            << "\tlayout->(" << layoutRect.x() << "," << layoutRect.y() << ") (" << layoutRect.width() << "x" << layoutRect.height() << ")"; 
        stream.nextLine();
    };

    auto renderBoxLikeMarginBox = [&] (const auto& boxGeometry) {
        if (layoutBox.isInitialContainingBlock())
            return BoxGeometry::borderBoxRect(boxGeometry);

        // Produce a RenderBox matching margin box.
        auto containingBlockWidth = layoutState.geometryForBox(layoutBox.containingBlock()).contentBoxWidth();
        auto marginStart = LayoutUnit { };
        auto& marginStartStyle = layoutBox.style().marginStart();
        if (marginStartStyle.isFixed() || marginStartStyle.isPercent() || marginStartStyle.isCalculated())
            marginStart = valueForLength(marginStartStyle, containingBlockWidth);

        auto marginEnd = LayoutUnit { };
        auto& marginEndStyle = layoutBox.style().marginEnd();
        if (marginEndStyle.isFixed() || marginEndStyle.isPercent() || marginEndStyle.isCalculated())
            marginEnd = valueForLength(marginEndStyle, containingBlockWidth);

        auto marginBefore = boxGeometry.marginBefore();
        auto marginAfter = boxGeometry.marginAfter();
        if (layoutBox.formattingContextRoot().establishesBlockFormattingContext()) {
            auto& formattingState = downcast<BlockFormattingState>(layoutState.formattingStateForBox(layoutBox));
            auto verticalMargin = formattingState.usedVerticalMargin(layoutBox);
            marginBefore = verticalMargin.nonCollapsedValues.before;
            marginAfter = verticalMargin.nonCollapsedValues.after;
        }
        auto borderBox = boxGeometry.borderBox();
        return Rect {
            borderBox.top() - marginBefore,
            borderBox.left() - marginStart,
            marginStart + borderBox.width() + marginEnd,
            marginBefore + borderBox.height() + marginAfter
        };
    };

    // rendering does not offset for relative positioned boxes.
    auto frameRect = renderer.frameRect();
    if (renderer.isInFlowPositioned())
        frameRect.move(renderer.offsetForInFlowPosition());

    auto boxGeometry = BoxGeometry { layoutState.geometryForBox(layoutBox) };
    if (layoutBox.isTableBox()) {
        // When the <table> is out-of-flow positioned, the wrapper table box has the offset
        // while the actual table box is static, inflow.
        auto& tableWrapperBoxGeometry = layoutState.geometryForBox(layoutBox.containingBlock());
        boxGeometry.moveBy(BoxGeometry::borderBoxTopLeft(tableWrapperBoxGeometry));
        // Table wrapper box has the margin values for the table.
        boxGeometry.setHorizontalMargin(tableWrapperBoxGeometry.horizontalMargin());
        boxGeometry.setVerticalMargin(tableWrapperBoxGeometry.verticalMargin());
    }

    if (is<RenderTableRow>(renderer) || is<RenderTableSection>(renderer)) {
        // Table rows and tbody have 0 width for some reason when border collapsing is on.
        if (is<RenderTableRow>(renderer) && downcast<RenderTableRow>(renderer).table()->collapseBorders())
            return false;
        // Section borders are either collapsed or ignored. However they may produce negative padding boxes.
        if (is<RenderTableSection>(renderer) && (downcast<RenderTableSection>(renderer).table()->collapseBorders() || renderer.style().hasBorder()))
            return false;
    }
    if (!areEssentiallyEqual(frameRect, BoxGeometry::borderBoxRect(boxGeometry))) {
        outputRect("frameBox", renderer.frameRect(), BoxGeometry::borderBoxRect(boxGeometry));
        return true;
    }

    if (!areEssentiallyEqual(renderer.borderBoxRect(), boxGeometry.borderBox())) {
        outputRect("borderBox", renderer.borderBoxRect(), boxGeometry.borderBox());
        return true;
    }

    // When the table row border overflows the row, padding box becomes negative and content box is incorrect.
    auto shouldCheckPaddingAndContentBox = !is<RenderTableRow>(renderer) || renderer.paddingBoxRect().width() >= 0;
    if (shouldCheckPaddingAndContentBox && !areEssentiallyEqual(renderer.paddingBoxRect(), boxGeometry.paddingBox())) {
        outputRect("paddingBox", renderer.paddingBoxRect(), boxGeometry.paddingBox());
        return true;
    }

    auto shouldCheckContentBox = [&] {
        if (!shouldCheckPaddingAndContentBox)
            return false;
        // FIXME: Figure out why trunk/rendering comes back with odd values for <tbody> and <td> content box.
        if (is<RenderTableCell>(renderer) || is<RenderTableSection>(renderer))
            return false;
        // Tables have 0 content box size for some reason when border collapsing is on.
        return !is<RenderTable>(renderer) || !downcast<RenderTable>(renderer).collapseBorders();
    }();
    if (shouldCheckContentBox && !areEssentiallyEqual(renderer.contentBoxRect(), boxGeometry.contentBox())) {
        outputRect("contentBox", renderer.contentBoxRect(), boxGeometry.contentBox());
        return true;
    }

    if (!areEssentiallyEqual(renderer.marginBoxRect(), renderBoxLikeMarginBox(boxGeometry))) {
        // In certain cases, like out-of-flow boxes with margin auto, marginBoxRect() returns 0. It's clearly incorrect,
        // so let's check the individual margin values instead (and at this point we know that all other boxes match).
        auto marginsMatch = boxGeometry.marginBefore() == renderer.marginBefore()
            && boxGeometry.marginAfter() == renderer.marginAfter()
            && boxGeometry.marginStart() == renderer.marginStart()
            && boxGeometry.marginEnd() == renderer.marginEnd();

        if (!marginsMatch) {
            outputRect("marginBox", renderer.marginBoxRect(), renderBoxLikeMarginBox(boxGeometry));
            return true;
        }
    }

    return false;
}

static bool verifyAndOutputSubtree(TextStream& stream, const LayoutState& context, const RenderBox& renderer, const Box& layoutBox)
{
    // Rendering code does not have the concept of table wrapper box. Skip it by verifying the first child(table box) instead. 
    if (layoutBox.isTableWrapperBox())
        return verifyAndOutputSubtree(stream, context, renderer, *downcast<ContainerBox>(layoutBox).firstChild()); 

    auto mismtachingGeometry = outputMismatchingBlockBoxInformationIfNeeded(stream, context, renderer, layoutBox);

    if (!is<ContainerBox>(layoutBox))
        return mismtachingGeometry;

    auto& containerBox = downcast<ContainerBox>(layoutBox);
    auto* childLayoutBox = containerBox.firstChild();
    auto* childRenderer = renderer.firstChild();

    while (childRenderer) {
        if (!is<RenderBox>(*childRenderer)) {
            childRenderer = childRenderer->nextSibling();
            continue;
        }

        if (!childLayoutBox) {
            stream  << "Trees are out of sync!";
            stream.nextLine();
            return true;
        }

        if (is<RenderBlockFlow>(*childRenderer) && childLayoutBox->establishesInlineFormattingContext()) {
            ASSERT(childRenderer->childrenInline());
            auto mismtachingGeometry = outputMismatchingBlockBoxInformationIfNeeded(stream, context, downcast<RenderBox>(*childRenderer), *childLayoutBox);
            if (mismtachingGeometry)
                return true;

            auto& blockFlow = downcast<RenderBlockFlow>(*childRenderer);
            auto& formattingRoot = downcast<ContainerBox>(*childLayoutBox);
            mismtachingGeometry |= outputMismatchingComplexLineInformationIfNeeded(stream, context, blockFlow, formattingRoot);
        } else {
            auto mismatchingSubtreeGeometry = verifyAndOutputSubtree(stream, context, downcast<RenderBox>(*childRenderer), *childLayoutBox);
            mismtachingGeometry |= mismatchingSubtreeGeometry;
        }

        childLayoutBox = childLayoutBox->nextSibling();
        childRenderer = childRenderer->nextSibling();
    }

    return mismtachingGeometry;
}

void LayoutContext::verifyAndOutputMismatchingLayoutTree(const LayoutState& layoutState, const RenderView& rootRenderer)
{
    TextStream stream;
    auto& layoutRoot = layoutState.root();
    auto mismatchingGeometry = verifyAndOutputSubtree(stream, layoutState, rootRenderer, layoutRoot);
    if (!mismatchingGeometry)
        return;
#if ENABLE(TREE_DEBUGGING)
    showRenderTree(&rootRenderer);
    showLayoutTree(layoutRoot, &layoutState);
#endif
    WTFLogAlways("%s", stream.release().utf8().data());
    ASSERT_NOT_REACHED();
}

}
}

#endif

#endif
