/*
 * 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 "LayerOverlapMap.h"
#include "Logging.h"
#include "RenderLayer.h"
#include <wtf/text/TextStream.h>

namespace WebCore {

struct RectList {
    Vector<LayoutRect> rects;
    LayoutRect boundingRect;
    
    void append(const LayoutRect& rect)
    {
        rects.append(rect);
        boundingRect.unite(rect);
    }

    void append(const RectList& rectList)
    {
        rects.appendVector(rectList.rects);
        boundingRect.unite(rectList.boundingRect);
    }
    
    bool intersects(const LayoutRect& rect) const
    {
        if (!rects.size() || !rect.intersects(boundingRect))
            return false;

        for (const auto& currentRect : rects) {
            if (currentRect.intersects(rect))
                return true;
        }
        return false;
    }
};

static TextStream& operator<<(TextStream& ts, const RectList& rectList)
{
    ts << "bounds " << rectList.boundingRect << " (" << rectList.rects << " rects)";
    return ts;
}

// Used to store overlap rects in a way that takes overflow into account.
// It stores a tree whose nodes are layers with composited scrolling. The tree is built lazily as layers are added whose containing block
// chains contain composited scrollers. The tree always starts at the root layer.
// Checking for overlap involves finding the node for the clipping layer enclosing the given layer (or the root),
// and comparing against the bounds of earlier siblings.
class OverlapMapContainer {
    WTF_MAKE_FAST_ALLOCATED;
public:
    OverlapMapContainer(const RenderLayer& rootLayer, const RenderLayer& scopeLayer)
        : m_rootScope(rootLayer)
        , m_scopeLayer(scopeLayer)
    {
    }

    // Layers are added in z-order, lazily creating clipping scopes as necessary.
    void add(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers);
    bool overlapsLayers(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const;
    void append(std::unique_ptr<OverlapMapContainer>&&);
    
    String dump(unsigned) const;
    
    const RenderLayer& scopeLayer() const { return m_scopeLayer; }

private:
    struct ClippingScope {
        ClippingScope(const RenderLayer& inLayer)
            : layer(inLayer)
        {
        }

        ClippingScope(const LayerOverlapMap::LayerAndBounds& layerAndBounds)
            : layer(layerAndBounds.layer)
            , bounds(layerAndBounds.bounds)
        {
        }

        ClippingScope* childWithLayer(const RenderLayer& layer) const
        {
            for (auto& child : children) {
                if (&child.layer == &layer)
                    return const_cast<ClippingScope*>(&child);
            }
            return nullptr;
        }

        ClippingScope* addChildWithLayerAndBounds(const LayerOverlapMap::LayerAndBounds& layerAndBounds)
        {
            children.append({ layerAndBounds });
            return &children.last();
        }

        ClippingScope* addChild(const ClippingScope& child)
        {
            ASSERT(&layer != &child.layer);
            children.append(child);
            return &children.last();
        }

        void appendRect(const LayoutRect& bounds)
        {
            rectList.append(bounds);
        }

        const RenderLayer& layer;
        LayoutRect bounds; // Bounds of the composited clip.
        Vector<ClippingScope> children;
        RectList rectList;
    };

    static ClippingScope* clippingScopeContainingLayerChildRecursive(const ClippingScope& currNode, const RenderLayer& layer)
    {
        for (auto& child : currNode.children) {
            if (&layer == &child.layer)
                return const_cast<ClippingScope*>(&currNode);

            if (auto* foundNode = clippingScopeContainingLayerChildRecursive(child, layer))
                return foundNode;
        }

        return nullptr;
    }

    ClippingScope* scopeContainingLayer(const RenderLayer& layer) const
    {
        return clippingScopeContainingLayerChildRecursive(m_rootScope, layer);
    }
    
    static void mergeClippingScopesRecursive(const ClippingScope& sourceScope, ClippingScope& destScope);

    ClippingScope* ensureClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers);
    ClippingScope* findClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const;

    void recursiveOutputToStream(TextStream&, const ClippingScope&, unsigned depth) const;

    const ClippingScope& rootScope() const { return m_rootScope; }
    ClippingScope& rootScope() { return m_rootScope; }

    ClippingScope m_rootScope;
    const RenderLayer& m_scopeLayer;
};

void OverlapMapContainer::add(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers)
{
    auto* layerScope = ensureClippingScopeForLayers(enclosingClippingLayers);
    layerScope->appendRect(bounds);
}

bool OverlapMapContainer::overlapsLayers(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const
{
    if (m_rootScope.rectList.intersects(bounds))
        return true;

    if (m_rootScope.children.isEmpty())
        return false;

    // Find the ClippingScope for which this layer is a child.
    auto* clippingScope = findClippingScopeForLayers(enclosingClippingLayers);
    if (!clippingScope)
        return false;

    if (clippingScope->rectList.intersects(bounds))
        return true;

    // FIXME: In some cases do we have to walk up the ancestor clipping scope chain?
    return false;
}

void OverlapMapContainer::mergeClippingScopesRecursive(const ClippingScope& sourceScope, ClippingScope& destScope)
{
    ASSERT(&sourceScope.layer == &destScope.layer);
    destScope.rectList.append(sourceScope.rectList);

    for (auto& sourceChildScope : sourceScope.children) {
        ClippingScope* destChild = destScope.childWithLayer(sourceChildScope.layer);
        if (destChild)
            mergeClippingScopesRecursive(sourceChildScope, *destChild);
        else {
            // New child, just copy the whole subtree.
            destScope.addChild(sourceChildScope);
        }
    }
}

void OverlapMapContainer::append(std::unique_ptr<OverlapMapContainer>&& otherContainer)
{
    mergeClippingScopesRecursive(otherContainer->rootScope(), m_rootScope);
}

OverlapMapContainer::ClippingScope* OverlapMapContainer::ensureClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers)
{
    ASSERT(enclosingClippingLayers.size());
    ASSERT(enclosingClippingLayers[0].layer.isRenderViewLayer());

    auto* currScope = &m_rootScope;
    for (unsigned i = 1; i < enclosingClippingLayers.size(); ++i) {
        auto& scopeLayerAndBounds = enclosingClippingLayers[i];
        auto* childScope = currScope->childWithLayer(scopeLayerAndBounds.layer);
        if (!childScope) {
            currScope = currScope->addChildWithLayerAndBounds(scopeLayerAndBounds);
            break;
        }

        currScope = childScope;
    }

    return const_cast<ClippingScope*>(currScope);
}

OverlapMapContainer::ClippingScope* OverlapMapContainer::findClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const
{
    ASSERT(enclosingClippingLayers.size());
    ASSERT(enclosingClippingLayers[0].layer.isRenderViewLayer());

    const auto* currScope = &m_rootScope;
    for (unsigned i = 1; i < enclosingClippingLayers.size(); ++i) {
        auto& scopeLayerAndBounds = enclosingClippingLayers[i];
        auto* childScope = currScope->childWithLayer(scopeLayerAndBounds.layer);
        if (!childScope)
            return nullptr;

        currScope = childScope;
    }

    return const_cast<ClippingScope*>(currScope);
}

void OverlapMapContainer::recursiveOutputToStream(TextStream& ts, const ClippingScope& scope, unsigned depth) const
{
    ts << "\n" << indent << TextStream::Repeat { 2 * depth, ' ' } << " scope for layer " << &scope.layer << " rects " << scope.rectList;
    for (auto& childScope : scope.children)
        recursiveOutputToStream(ts, childScope, depth + 1);
}

String OverlapMapContainer::dump(unsigned indent) const
{
    TextStream multilineStream;
    multilineStream.increaseIndent(indent);
    multilineStream << "overlap container - root layer " <<  &m_rootScope.layer << " scope layer " << &m_scopeLayer << " rects " << m_rootScope.rectList;

    for (auto& childScope : m_rootScope.children)
        recursiveOutputToStream(multilineStream, childScope, 1);

    return multilineStream.release();
}

LayerOverlapMap::LayerOverlapMap(const RenderLayer& rootLayer)
    : m_geometryMap(UseTransforms)
    , m_rootLayer(rootLayer)
{
    // Begin assuming the root layer will be composited so that there is
    // something on the stack. The root layer should also never get an
    // popCompositingContainer call.
    pushCompositingContainer(rootLayer);
}

LayerOverlapMap::~LayerOverlapMap() = default;

void LayerOverlapMap::add(const RenderLayer& layer, const LayoutRect& bounds, const Vector<LayerAndBounds>& enclosingClippingLayers)
{
    // Layers do not contribute to overlap immediately--instead, they will
    // contribute to overlap as soon as their composited ancestor has been
    // recursively processed and popped off the stack.
    ASSERT(m_overlapStack.size() >= 2);
    auto& container = m_overlapStack[m_overlapStack.size() - 2];
    container->add(layer, bounds, enclosingClippingLayers);

    LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " contributes to overlap in the scope of layer " << &container->scopeLayer() << ", added to map " << *this);

    m_isEmpty = false;
}

bool LayerOverlapMap::overlapsLayers(const RenderLayer& layer, const LayoutRect& bounds, const Vector<LayerAndBounds>& enclosingClippingLayers) const
{
    return m_overlapStack.last()->overlapsLayers(layer, bounds, enclosingClippingLayers);
}

void LayerOverlapMap::pushCompositingContainer(const RenderLayer& layer)
{
    m_overlapStack.append(makeUnique<OverlapMapContainer>(m_rootLayer, layer));
}

void LayerOverlapMap::popCompositingContainer(const RenderLayer& layer)
{
    ASSERT_UNUSED(layer, &m_overlapStack.last()->scopeLayer() == &layer);
    m_overlapStack[m_overlapStack.size() - 2]->append(WTFMove(m_overlapStack.last()));
    m_overlapStack.removeLast();
}

static TextStream& operator<<(TextStream& ts, const OverlapMapContainer& container)
{
    ts << container.dump(ts.indent());
    return ts;
}

TextStream& operator<<(TextStream& ts, const LayerOverlapMap& overlapMap)
{
    TextStream multilineStream;

    TextStream::GroupScope scope(ts);
    multilineStream << "LayerOverlapMap\n";
    multilineStream.increaseIndent(2);

    bool needNewline = false;
    for (auto& container : overlapMap.overlapStack()) {
        if (needNewline)
            multilineStream << "\n";
        else
            needNewline = true;
        multilineStream << indent << *container;
    }

    ts << multilineStream.release();
    return ts;
}

} // namespace WebCore

