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

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

#include "CachedImage.h"
#include "Color.h"
#include "DisplayBox.h"
#include "GraphicsContext.h"
#include "InlineFormattingState.h"
#include "InlineTextItem.h"
#include "IntRect.h"
#include "LayoutContainerBox.h"
#include "LayoutInitialContainingBlock.h"
#include "LayoutState.h"
#include "RenderStyle.h"
#include "TextRun.h"

namespace WebCore {
namespace Display {

static void paintBoxDecoration(GraphicsContext& context, const Box& absoluteDisplayBox, const RenderStyle& style, bool needsMarginPainting)
{
    auto decorationBoxTopLeft = needsMarginPainting ? absoluteDisplayBox.rectWithMargin().topLeft() : absoluteDisplayBox.topLeft();
    auto decorationBoxSize = needsMarginPainting ? absoluteDisplayBox.rectWithMargin().size() : LayoutSize(absoluteDisplayBox.borderBoxWidth(), absoluteDisplayBox.borderBoxHeight());
    // Background color
    if (style.hasBackground()) {
        context.fillRect({ decorationBoxTopLeft, decorationBoxSize }, style.backgroundColor());
        if (style.hasBackgroundImage()) {
            auto& backgroundLayer = style.backgroundLayers();
            if (backgroundLayer.image() && backgroundLayer.image()->cachedImage() && backgroundLayer.image()->cachedImage()->image())
                context.drawImage(*backgroundLayer.image()->cachedImage()->image(), { decorationBoxTopLeft, backgroundLayer.image()->cachedImage()->image()->size() });
        }
    }

    // Border
    if (style.hasVisibleBorder()) {

        auto drawBorderSide = [&](auto start, auto end, const auto& borderStyle) {
            if (!borderStyle.width())
                return;
            if (borderStyle.style() == BorderStyle::None || borderStyle.style() == BorderStyle::Hidden)
                return;
            context.setStrokeColor(borderStyle.color());
            context.setStrokeThickness(borderStyle.width());
            context.drawLine(start, end);
        };

        context.setFillColor(Color::transparent);

        auto decorationBoxWidth = decorationBoxSize.width();
        auto decorationBoxHeight = decorationBoxSize.height();

        // Top
        {
            auto borderWidth = style.borderTop().width();
            auto start = LayoutPoint { decorationBoxTopLeft };
            auto end = LayoutPoint { start.x() + decorationBoxWidth, start.y() + borderWidth };
            drawBorderSide(start, end, style.borderTop());
        }

        // Right
        {
            auto borderWidth = style.borderRight().width();
            auto start = LayoutPoint { decorationBoxTopLeft.x() + decorationBoxWidth - borderWidth, decorationBoxTopLeft.y() };
            auto end = LayoutPoint { start.x() + borderWidth, decorationBoxTopLeft.y() + decorationBoxHeight };
            drawBorderSide(start, end, style.borderRight());
        }

        // Bottom
        {
            auto borderWidth = style.borderBottom().width();
            auto start = LayoutPoint { decorationBoxTopLeft.x(), decorationBoxTopLeft.y() + decorationBoxHeight - borderWidth };
            auto end = LayoutPoint { start.x() + decorationBoxWidth, start.y() + borderWidth };
            drawBorderSide(start, end, style.borderBottom());
        }

        // Left
        {
            auto borderWidth = style.borderLeft().width();
            auto start = decorationBoxTopLeft;
            auto end = LayoutPoint { start.x() + borderWidth, decorationBoxTopLeft.y() + decorationBoxHeight };
            drawBorderSide(start, end, style.borderLeft());
        }
    }
}

static void paintInlineContent(GraphicsContext& context, LayoutPoint absoluteOffset, const Layout::InlineFormattingState& formattingState)
{
    auto* displayInlineContent = formattingState.displayInlineContent();
    if (!displayInlineContent)
        return;

    auto& displayRuns = displayInlineContent->runs;
    if (displayRuns.isEmpty())
        return;

    for (auto& run : displayRuns) {
        if (auto& textContent = run.textContent()) {
            auto& style = run.style();
            context.setStrokeColor(style.color());
            context.setFillColor(style.color());

            auto absoluteLeft = absoluteOffset.x() + run.left();
            // FIXME: Add non-baseline align painting
            auto& lineBox = displayInlineContent->lineBoxForRun(run);
            auto baselineOffset = absoluteOffset.y() + lineBox.top() + lineBox.baselineOffset();
            auto expansion = run.expansion();
            auto textRun = TextRun { textContent->content(), run.left() - lineBox.left(), expansion.horizontalExpansion, expansion.behavior };
            textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
            context.drawText(style.fontCascade(), textRun, { absoluteLeft, baselineOffset });
        } else if (auto* cachedImage = run.image()) {
            auto runAbsoluteRect = FloatRect { absoluteOffset.x() + run.left(), absoluteOffset.y() + run.top(), run.width(), run.height() };
            context.drawImage(*cachedImage->image(), runAbsoluteRect);
        }
    }
}

static Box absoluteDisplayBox(const Layout::LayoutState& layoutState, const Layout::Box& layoutBox)
{
    // Should never really happen but table code is way too incomplete.
    if (!layoutState.hasDisplayBox(layoutBox))
        return { };
    if (is<Layout::InitialContainingBlock>(layoutBox))
        return layoutState.displayBoxForLayoutBox(layoutBox);

    auto absoluteBox = Box { layoutState.displayBoxForLayoutBox(layoutBox) };
    for (auto* containingBlock = &layoutBox.containingBlock(); !is<Layout::InitialContainingBlock>(*containingBlock); containingBlock = &containingBlock->containingBlock())
        absoluteBox.moveBy(layoutState.displayBoxForLayoutBox(*containingBlock).topLeft());
    return absoluteBox;
}

static bool isPaintRootCandidate(const Layout::Box& layoutBox)
{
    return layoutBox.isPositioned();
}

using LayoutBoxList = Vector<const Layout::Box*>;

enum PaintPhase { Decoration, Content };
static void paintSubtree(GraphicsContext& context, const Layout::LayoutState& layoutState, const Layout::Box& paintRootBox, const IntRect& dirtyRect, PaintPhase paintPhase)
{
    auto paint = [&] (auto& layoutBox) {
        if (layoutBox.style().visibility() != Visibility::Visible)
            return;
        if (!layoutState.hasDisplayBox(layoutBox))
            return;
        auto absoluteDisplayBox = Display::absoluteDisplayBox(layoutState, layoutBox);
        if (!dirtyRect.intersects(snappedIntRect(absoluteDisplayBox.rect())))
            return;

        if (paintPhase == PaintPhase::Decoration) {
            if (layoutBox.isAnonymous())
                return;
            paintBoxDecoration(context, absoluteDisplayBox, layoutBox.style(), layoutBox.isBodyBox());
            return;
        }
        // Only inline content for now.
        if (layoutBox.establishesInlineFormattingContext()) {
            auto& containerBox = downcast<Layout::ContainerBox>(layoutBox);
            paintInlineContent(context, absoluteDisplayBox.topLeft(), layoutState.establishedInlineFormattingState(containerBox));
        }
    };

    paint(paintRootBox);
    if (!is<Layout::ContainerBox>(paintRootBox) || !downcast<Layout::ContainerBox>(paintRootBox).hasChild())
        return;

    LayoutBoxList layoutBoxList;
    layoutBoxList.append(downcast<Layout::ContainerBox>(paintRootBox).firstChild());
    while (!layoutBoxList.isEmpty()) {
        while (true) {
            auto& layoutBox = *layoutBoxList.last();
            if (isPaintRootCandidate(layoutBox))
                break;
            paint(layoutBox);
            if (!is<Layout::ContainerBox>(layoutBox) || !downcast<Layout::ContainerBox>(layoutBox).hasChild())
                break;
            layoutBoxList.append(downcast<Layout::ContainerBox>(layoutBox).firstChild());
        }
        while (!layoutBoxList.isEmpty()) {
            auto& layoutBox = *layoutBoxList.takeLast();
            // Stay within.
            if (&layoutBox == &paintRootBox)
                return;
            if (auto* nextSibling = layoutBox.nextSibling()) {
                layoutBoxList.append(nextSibling);
                break;
            }
        }
    }
}

static LayoutRect collectPaintRootsAndContentRect(const Layout::LayoutState& layoutState, const Layout::Box& rootLayoutBox, LayoutBoxList& positiveZOrderList, LayoutBoxList& negativeZOrderList)
{
    auto appendPaintRoot = [&] (const auto& layoutBox) {
        if (layoutBox.style().usedZIndex() < 0) {
            negativeZOrderList.append(&layoutBox);
            return;
        }
        positiveZOrderList.append(&layoutBox);
    };

    auto contentRect = LayoutRect { layoutState.displayBoxForLayoutBox(rootLayoutBox).rect() };

    // Initial BFC is always a paint root.
    appendPaintRoot(rootLayoutBox);
    LayoutBoxList layoutBoxList;
    layoutBoxList.append(&rootLayoutBox);
    while (!layoutBoxList.isEmpty()) {
        while (true) {
            auto& layoutBox = *layoutBoxList.last();
            if (layoutBox.style().visibility() != Visibility::Visible)
                break;
            if (isPaintRootCandidate(layoutBox))
                appendPaintRoot(layoutBox);
            if (layoutState.hasDisplayBox(layoutBox))
                contentRect.uniteIfNonZero(Display::absoluteDisplayBox(layoutState, layoutBox).rect());
            if (!is<Layout::ContainerBox>(layoutBox) || !downcast<Layout::ContainerBox>(layoutBox).hasChild())
                break;
            layoutBoxList.append(downcast<Layout::ContainerBox>(layoutBox).firstChild());
        }
        while (!layoutBoxList.isEmpty()) {
            auto& layoutBox = *layoutBoxList.takeLast();
            if (auto* nextSibling = layoutBox.nextSibling()) {
                layoutBoxList.append(nextSibling);
                break;
            }
        }
    }

    auto compareZIndex = [] (const Layout::Box* a, const Layout::Box* b) {
        return a->style().usedZIndex() < b->style().usedZIndex();
    };

    std::stable_sort(positiveZOrderList.begin(), positiveZOrderList.end(), compareZIndex);
    std::stable_sort(negativeZOrderList.begin(), negativeZOrderList.end(), compareZIndex);
    return contentRect;
}

void Painter::paint(const Layout::LayoutState& layoutState, GraphicsContext& context, const IntRect& dirtyRect)
{
    auto& rootLayoutBox = layoutState.root();
    if (!rootLayoutBox.firstChild())
        return;

    Vector<const Layout::Box*> negativeZOrderList;
    Vector<const Layout::Box*> positiveZOrderList;
    auto contentRect = collectPaintRootsAndContentRect(layoutState, rootLayoutBox, positiveZOrderList, negativeZOrderList);

    // Fill the entire content area.
    context.fillRect(contentRect, Color::white);

    for (auto& paintRootBox : negativeZOrderList) {
        paintSubtree(context, layoutState, *paintRootBox, dirtyRect, PaintPhase::Decoration);
        paintSubtree(context, layoutState, *paintRootBox, dirtyRect, PaintPhase::Content);
    }

    for (auto& paintRootBox : positiveZOrderList) {
        paintSubtree(context, layoutState, *paintRootBox, dirtyRect, PaintPhase::Decoration);
        paintSubtree(context, layoutState, *paintRootBox, dirtyRect, PaintPhase::Content);
    }
}

void Painter::paintInlineFlow(const Layout::LayoutState& layoutState, GraphicsContext& context)
{
    auto& layoutRoot = layoutState.root();

    ASSERT(layoutRoot.establishesInlineFormattingContext());

    paintInlineContent(context, { }, layoutState.establishedInlineFormattingState(layoutRoot));
}

}
}

#endif
