/*
 * Copyright (C) 2014-2017 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 "PageOverlayController.h"

#include "Chrome.h"
#include "ChromeClient.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "GraphicsLayer.h"
#include "Page.h"
#include "PageOverlay.h"
#include "ScrollingCoordinator.h"
#include "Settings.h"
#include "TiledBacking.h"

// FIXME: Someone needs to call didChangeSettings() if we want dynamic updates of layer border/repaint counter settings.

namespace WebCore {

PageOverlayController::PageOverlayController(Page& page)
    :  m_page(page)
{
}

PageOverlayController::~PageOverlayController() = default;

void PageOverlayController::createRootLayersIfNeeded()
{
    if (m_initialized)
        return;

    m_initialized = true;

    ASSERT(!m_documentOverlayRootLayer);
    ASSERT(!m_viewOverlayRootLayer);

    m_documentOverlayRootLayer = GraphicsLayer::create(m_page.chrome().client().graphicsLayerFactory(), *this);
    m_viewOverlayRootLayer = GraphicsLayer::create(m_page.chrome().client().graphicsLayerFactory(), *this);
    m_documentOverlayRootLayer->setName(MAKE_STATIC_STRING_IMPL("Document overlay Container"));
    m_viewOverlayRootLayer->setName(MAKE_STATIC_STRING_IMPL("View overlay container"));
}

void PageOverlayController::installedPageOverlaysChanged()
{
    if (hasViewOverlays())
        attachViewOverlayLayers();
    else
        detachViewOverlayLayers();

    if (auto* frameView = m_page.mainFrame().view())
        frameView->setNeedsCompositingConfigurationUpdate();

    updateForceSynchronousScrollLayerPositionUpdates();
}

bool PageOverlayController::hasDocumentOverlays() const
{
    for (const auto& overlay : m_pageOverlays) {
        if (overlay->overlayType() == PageOverlay::OverlayType::Document)
            return true;
    }
    return false;
}

bool PageOverlayController::hasViewOverlays() const
{
    for (const auto& overlay : m_pageOverlays) {
        if (overlay->overlayType() == PageOverlay::OverlayType::View)
            return true;
    }
    return false;
}

void PageOverlayController::attachViewOverlayLayers()
{
    if (hasViewOverlays())
        m_page.chrome().client().attachViewOverlayGraphicsLayer(&layerWithViewOverlays());
}

void PageOverlayController::detachViewOverlayLayers()
{
    m_page.chrome().client().attachViewOverlayGraphicsLayer(nullptr);
}

GraphicsLayer* PageOverlayController::documentOverlayRootLayer() const
{
    return m_documentOverlayRootLayer.get();
}

GraphicsLayer* PageOverlayController::viewOverlayRootLayer() const
{
    return m_viewOverlayRootLayer.get();
}

static void updateOverlayGeometry(PageOverlay& overlay, GraphicsLayer& graphicsLayer)
{
    IntRect overlayFrame = overlay.frame();

    if (overlayFrame.location() == graphicsLayer.position() && overlayFrame.size() == graphicsLayer.size())
        return;

    graphicsLayer.setPosition(overlayFrame.location());
    graphicsLayer.setSize(overlayFrame.size());
}

GraphicsLayer& PageOverlayController::layerWithDocumentOverlays()
{
    createRootLayersIfNeeded();

    bool inWindow = m_page.isInWindow();

    for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
        PageOverlay& overlay = *overlayAndLayer.key;
        if (overlay.overlayType() != PageOverlay::OverlayType::Document)
            continue;

        auto& layer = overlayAndLayer.value;
        GraphicsLayer::traverse(layer.get(), [inWindow](GraphicsLayer& layer) {
            layer.setIsInWindow(inWindow);
        });
        updateOverlayGeometry(overlay, layer.get());
        
        if (!layer->parent())
            m_documentOverlayRootLayer->addChild(layer.copyRef());
    }

    return *m_documentOverlayRootLayer;
}

GraphicsLayer& PageOverlayController::layerWithViewOverlays()
{
    createRootLayersIfNeeded();

    bool inWindow = m_page.isInWindow();

    for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
        PageOverlay& overlay = *overlayAndLayer.key;
        if (overlay.overlayType() != PageOverlay::OverlayType::View)
            continue;

        auto& layer = overlayAndLayer.value;
        GraphicsLayer::traverse(layer.get(), [inWindow](GraphicsLayer& layer) {
            layer.setIsInWindow(inWindow);
        });
        updateOverlayGeometry(overlay, layer.get());
        
        if (!layer->parent())
            m_viewOverlayRootLayer->addChild(layer.copyRef());
    }

    return *m_viewOverlayRootLayer;
}

void PageOverlayController::installPageOverlay(PageOverlay& overlay, PageOverlay::FadeMode fadeMode)
{
    createRootLayersIfNeeded();

    if (m_pageOverlays.contains(&overlay))
        return;

    m_pageOverlays.append(&overlay);

    auto layer = GraphicsLayer::create(m_page.chrome().client().graphicsLayerFactory(), *this);
    layer->setAnchorPoint({ });
    layer->setBackgroundColor(overlay.backgroundColor());
    layer->setName(MAKE_STATIC_STRING_IMPL("Overlay content"));

    updateSettingsForLayer(layer.get());

    switch (overlay.overlayType()) {
    case PageOverlay::OverlayType::View:
        m_viewOverlayRootLayer->addChild(layer.get());
        break;
    case PageOverlay::OverlayType::Document:
        m_documentOverlayRootLayer->addChild(layer.get());
        break;
    }

    auto& rawLayer = layer.get();
    m_overlayGraphicsLayers.set(&overlay, WTFMove(layer));

    overlay.setPage(&m_page);

    if (FrameView* frameView = m_page.mainFrame().view())
        frameView->enterCompositingMode();

    updateOverlayGeometry(overlay, rawLayer);

    if (fadeMode == PageOverlay::FadeMode::Fade)
        overlay.startFadeInAnimation();

    installedPageOverlaysChanged();
}

void PageOverlayController::uninstallPageOverlay(PageOverlay& overlay, PageOverlay::FadeMode fadeMode)
{
    if (fadeMode == PageOverlay::FadeMode::Fade) {
        overlay.startFadeOutAnimation();
        return;
    }

    overlay.setPage(nullptr);

    if (auto optionalLayer = m_overlayGraphicsLayers.take(&overlay))
        optionalLayer->removeFromParent();

    bool removed = m_pageOverlays.removeFirst(&overlay);
    ASSERT_UNUSED(removed, removed);

    installedPageOverlaysChanged();
}

void PageOverlayController::updateForceSynchronousScrollLayerPositionUpdates()
{
#if ENABLE(ASYNC_SCROLLING)
    bool forceSynchronousScrollLayerPositionUpdates = false;

    for (auto& overlay : m_pageOverlays) {
        if (overlay->needsSynchronousScrolling())
            forceSynchronousScrollLayerPositionUpdates = true;
    }

    if (ScrollingCoordinator* scrollingCoordinator = m_page.scrollingCoordinator())
        scrollingCoordinator->setForceSynchronousScrollLayerPositionUpdates(forceSynchronousScrollLayerPositionUpdates);
#endif
}

void PageOverlayController::setPageOverlayNeedsDisplay(PageOverlay& overlay, const IntRect& dirtyRect)
{
    ASSERT(m_pageOverlays.contains(&overlay));
    auto* graphicsLayer = m_overlayGraphicsLayers.get(&overlay);

    if (!graphicsLayer->drawsContent()) {
        graphicsLayer->setDrawsContent(true);
        updateOverlayGeometry(overlay, *graphicsLayer);
    }

    graphicsLayer->setNeedsDisplayInRect(dirtyRect);
}

void PageOverlayController::setPageOverlayOpacity(PageOverlay& overlay, float opacity)
{
    ASSERT(m_pageOverlays.contains(&overlay));
    m_overlayGraphicsLayers.get(&overlay)->setOpacity(opacity);
}

void PageOverlayController::clearPageOverlay(PageOverlay& overlay)
{
    ASSERT(m_pageOverlays.contains(&overlay));
    m_overlayGraphicsLayers.get(&overlay)->setDrawsContent(false);
}

GraphicsLayer& PageOverlayController::layerForOverlay(PageOverlay& overlay) const
{
    ASSERT(m_pageOverlays.contains(&overlay));
    return *m_overlayGraphicsLayers.get(&overlay);
}

void PageOverlayController::didChangeViewSize()
{
    for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
        if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View)
            updateOverlayGeometry(*overlayAndLayer.key, overlayAndLayer.value.get());
    }
}

void PageOverlayController::didChangeDocumentSize()
{
    for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
        if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::Document)
            updateOverlayGeometry(*overlayAndLayer.key, overlayAndLayer.value.get());
    }
}

void PageOverlayController::didChangeSettings()
{
    // FIXME: We should apply these settings to all overlay sublayers recursively.
    for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
        updateSettingsForLayer(graphicsLayer.get());
}

void PageOverlayController::didChangeDeviceScaleFactor()
{
    if (!m_initialized)
        return;

    m_documentOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
    m_viewOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();

    for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
        graphicsLayer->setNeedsDisplay();
}

void PageOverlayController::didChangeViewExposedRect()
{
    m_page.scheduleRenderingUpdate(RenderingUpdateStep::LayerFlush);
}

void PageOverlayController::didScrollFrame(Frame& frame)
{
    for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
        if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View || !frame.isMainFrame())
            overlayAndLayer.value->setNeedsDisplay();
        overlayAndLayer.key->didScrollFrame(frame);
    }
}

void PageOverlayController::updateSettingsForLayer(GraphicsLayer& layer)
{
    Settings& settings = m_page.settings();
    layer.setAcceleratesDrawing(settings.acceleratedDrawingEnabled());
    layer.setShowDebugBorder(settings.showDebugBorders());
    layer.setShowRepaintCounter(settings.showRepaintCounter());
}

bool PageOverlayController::handleMouseEvent(const PlatformMouseEvent& mouseEvent)
{
    if (m_pageOverlays.isEmpty())
        return false;

    for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
        if ((*it)->mouseEvent(mouseEvent))
            return true;
    }

    return false;
}

bool PageOverlayController::copyAccessibilityAttributeStringValueForPoint(String attribute, FloatPoint parameter, String& value)
{
    if (m_pageOverlays.isEmpty())
        return false;

    for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
        if ((*it)->copyAccessibilityAttributeStringValueForPoint(attribute, parameter, value))
            return true;
    }

    return false;
}

bool PageOverlayController::copyAccessibilityAttributeBoolValueForPoint(String attribute, FloatPoint parameter, bool& value)
{
    if (m_pageOverlays.isEmpty())
        return false;

    for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
        if ((*it)->copyAccessibilityAttributeBoolValueForPoint(attribute, parameter, value))
            return true;
    }
    
    return false;
}

Vector<String> PageOverlayController::copyAccessibilityAttributesNames(bool parameterizedNames)
{
    if (m_pageOverlays.isEmpty())
        return { };

    for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
        Vector<String> names = (*it)->copyAccessibilityAttributeNames(parameterizedNames);
        if (!names.isEmpty())
            return names;
    }

    return { };
}

void PageOverlayController::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, const FloatRect& clipRect, GraphicsLayerPaintBehavior)
{
    for (auto& overlayAndGraphicsLayer : m_overlayGraphicsLayers) {
        if (overlayAndGraphicsLayer.value.ptr() != graphicsLayer)
            continue;

        GraphicsContextStateSaver stateSaver(graphicsContext);
        graphicsContext.clip(clipRect);
        overlayAndGraphicsLayer.key->drawRect(graphicsContext, enclosingIntRect(clipRect));

        return;
    }
}

float PageOverlayController::deviceScaleFactor() const
{
    return m_page.deviceScaleFactor();
}

void PageOverlayController::notifyFlushRequired(const GraphicsLayer*)
{
    m_page.scheduleRenderingUpdate(RenderingUpdateStep::LayerFlush);
}

void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)
{
    ASSERT(m_pageOverlays.contains(&overlay));
    if (auto* layer = m_overlayGraphicsLayers.get(&overlay))
        updateOverlayGeometry(overlay, *layer);
}

void PageOverlayController::didChangeOverlayBackgroundColor(PageOverlay& overlay)
{
    ASSERT(m_pageOverlays.contains(&overlay));
    if (auto* layer = m_overlayGraphicsLayers.get(&overlay))
        layer->setBackgroundColor(overlay.backgroundColor());
}

bool PageOverlayController::shouldSkipLayerInDump(const GraphicsLayer*, OptionSet<LayerTreeAsTextOptions> options) const
{
    return !options.contains(LayerTreeAsTextOptions::IncludePageOverlayLayers);
}

void PageOverlayController::tiledBackingUsageChanged(const GraphicsLayer* graphicsLayer, bool usingTiledBacking)
{
    if (usingTiledBacking)
        graphicsLayer->tiledBacking()->setIsInWindow(m_page.isInWindow());
}

} // namespace WebKit
