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

#include "ColorHash.h"
#include "Cursor.h"
#include "ElementIterator.h"
#include "FloatRoundedRect.h"
#include "FrameView.h"
#include "Gradient.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
#include "InteractionRegion.h"
#include "Page.h"
#include "PageOverlay.h"
#include "PageOverlayController.h"
#include "PathUtilities.h"
#include "PlatformMouseEvent.h"
#include "Region.h"
#include "RenderLayer.h"
#include "RenderLayerBacking.h"
#include "RenderView.h"
#include "ScrollingCoordinator.h"
#include "Settings.h"
#include <wtf/SortedArrayMap.h>

namespace WebCore {

DebugPageOverlays* DebugPageOverlays::sharedDebugOverlays;

class RegionOverlay : public RefCounted<RegionOverlay>, public PageOverlay::Client {
public:
    static Ref<RegionOverlay> create(Page&, DebugPageOverlays::RegionType);
    virtual ~RegionOverlay();

    void recomputeRegion();
    PageOverlay& overlay() { return *m_overlay; }

    void setRegionChanged() { m_regionChanged = true; }

    virtual bool shouldPaintOverlayIntoLayer() const { return true; }

protected:
    RegionOverlay(Page&, Color);

private:
    void willMoveToPage(PageOverlay&, Page*) final;
    void didMoveToPage(PageOverlay&, Page*) final;
    void drawRect(PageOverlay&, GraphicsContext&, const IntRect& dirtyRect) override;
    bool mouseEvent(PageOverlay&, const PlatformMouseEvent&) override;
    void didScrollFrame(PageOverlay&, Frame&) override;

protected:
    // Returns true if the region changed.
    virtual bool updateRegion() = 0;
    void drawRegion(GraphicsContext&, const Region&, const Color&, const IntRect& dirtyRect);
    
    Page& m_page;
    RefPtr<PageOverlay> m_overlay;
    std::unique_ptr<Region> m_region;
    Color m_color;
    bool m_regionChanged { true };
};

#if COMPILER(CLANG)
#pragma mark - MouseWheelRegionOverlay
#endif

class MouseWheelRegionOverlay final : public RegionOverlay {
public:
    static Ref<MouseWheelRegionOverlay> create(Page& page)
    {
        return adoptRef(*new MouseWheelRegionOverlay(page));
    }

private:
    explicit MouseWheelRegionOverlay(Page& page)
        : RegionOverlay(page, SRGBA<uint8_t> { 128, 0, 0, 102 })
    {
    }

    bool updateRegion() override;
};

bool MouseWheelRegionOverlay::updateRegion()
{
#if ENABLE(WHEEL_EVENT_REGIONS)
    // Wheel event regions are painted via RenderLayerBacking::paintDebugOverlays().
    return false;
#else
    auto region = makeUnique<Region>();
    
    for (const Frame* frame = &m_page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
        if (!frame->view() || !frame->document())
            continue;

        auto frameRegion = frame->document()->absoluteRegionForEventTargets(frame->document()->wheelEventTargets());
        frameRegion.first.translate(toIntSize(frame->view()->contentsToRootView(IntPoint())));
        region->unite(frameRegion.first);
    }
    
    region->translate(m_overlay->viewToOverlayOffset());

    bool regionChanged = !m_region || !(*m_region == *region);
    m_region = WTFMove(region);
    return regionChanged;
#endif
}

#if COMPILER(CLANG)
#pragma mark - NonFastScrollableRegionOverlay
#endif

class NonFastScrollableRegionOverlay final : public RegionOverlay {
public:
    static Ref<NonFastScrollableRegionOverlay> create(Page& page)
    {
        return adoptRef(*new NonFastScrollableRegionOverlay(page));
    }

private:
    explicit NonFastScrollableRegionOverlay(Page& page)
        : RegionOverlay(page, Color::orange.colorWithAlphaByte(102))
    {
    }

    bool updateRegion() override;
    void drawRect(PageOverlay&, GraphicsContext&, const IntRect& dirtyRect) final;
    
    EventTrackingRegions m_eventTrackingRegions;
};

bool NonFastScrollableRegionOverlay::updateRegion()
{
    bool regionChanged = false;

    if (ScrollingCoordinator* scrollingCoordinator = m_page.scrollingCoordinator()) {
        EventTrackingRegions eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();

        if (eventTrackingRegions != m_eventTrackingRegions) {
            m_eventTrackingRegions = eventTrackingRegions;
            regionChanged = true;
        }
    }

    return regionChanged;
}

static void drawRightAlignedText(const String& text, GraphicsContext& context, const FontCascade& font, const FloatPoint& boxLocation)
{
    float textGap = 10;
    float textBaselineFromTop = 14;

    TextRun textRun = TextRun(text);
    float textWidth = font.width(textRun);
    context.setFillColor(Color::black);
    context.drawText(font, textRun, boxLocation + FloatSize(-(textWidth + textGap), textBaselineFromTop));
}

void NonFastScrollableRegionOverlay::drawRect(PageOverlay& pageOverlay, GraphicsContext& context, const IntRect&)
{
    static constexpr std::pair<EventTrackingRegions::EventType, SRGBA<uint8_t>> colorMappings[] = {
        { EventTrackingRegions::EventType::Mousedown, { 80, 245, 80, 50 } },
        { EventTrackingRegions::EventType::Mousemove, { 245, 245, 80, 50 } },
        { EventTrackingRegions::EventType::Mouseup, { 80, 245, 176, 50 } },
        { EventTrackingRegions::EventType::Touchend, { 191, 63, 127, 50 } },
        { EventTrackingRegions::EventType::Touchforcechange, { 63, 63, 191, 50 } },
        { EventTrackingRegions::EventType::Touchmove, { 80, 204, 245, 50 } },
        { EventTrackingRegions::EventType::Touchstart, { 191, 191, 63, 50 } },
        { EventTrackingRegions::EventType::Wheel, { 255, 128, 0, 50 } },
    };
    constexpr SortedArrayMap colors { colorMappings };
    constexpr auto defaultColor = Color::black.colorWithAlphaByte(64);

    IntRect bounds = pageOverlay.bounds();
    
    context.clearRect(bounds);
    
    FloatRect legendRect = { bounds.maxX() - 30.0f, 10, 20, 20 };
    
    FontCascadeDescription fontDescription;
    fontDescription.setOneFamily("Helvetica"_s);
    fontDescription.setSpecifiedSize(12);
    fontDescription.setComputedSize(12);
    fontDescription.setWeight(FontSelectionValue(500));
    FontCascade font(WTFMove(fontDescription), 0, 0);
    font.update(nullptr);

    auto drawLegend = [&] (const Color& color, ASCIILiteral text) {
        context.setFillColor(color);
        context.fillRect(legendRect);
        drawRightAlignedText(text, context, font, legendRect.location());
        legendRect.move(0, 30);
    };

#if ENABLE(TOUCH_EVENTS)
    auto drawEventLegend = [&](EventTrackingRegions::EventType eventType) {
        drawLegend(colors.get(eventType), EventTrackingRegions::eventName(eventType));
    };
    drawEventLegend(EventTrackingRegions::EventType::Touchstart);
    drawEventLegend(EventTrackingRegions::EventType::Touchmove);
    drawEventLegend(EventTrackingRegions::EventType::Touchend);
    drawEventLegend(EventTrackingRegions::EventType::Touchforcechange);
    drawLegend(m_color, "passive listeners"_s);
    drawEventLegend(EventTrackingRegions::EventType::Mousedown);
    drawEventLegend(EventTrackingRegions::EventType::Mousemove);
    drawEventLegend(EventTrackingRegions::EventType::Mouseup);
#else
    // On desktop platforms, the "wheel" region includes the non-fast scrollable region.
    drawLegend(colors.get(EventTrackingRegions::EventType::Wheel), "non-fast region"_s);
#endif

    for (auto& region : m_eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
        drawRegion(context, region.value, colors.get(region.key, defaultColor), bounds);
    drawRegion(context, m_eventTrackingRegions.asynchronousDispatchRegion, m_color, bounds);
}

#if COMPILER(CLANG)
#pragma mark - InteractionRegionOverlay
#endif

class InteractionRegionOverlay final : public RegionOverlay {
public:
    static Ref<InteractionRegionOverlay> create(Page& page)
    {
        return adoptRef(*new InteractionRegionOverlay(page));
    }

private:
    explicit InteractionRegionOverlay(Page& page)
        : RegionOverlay(page, Color::green.colorWithAlphaByte(102))
    {
    }

    bool updateRegion() final;
    void drawRect(PageOverlay&, GraphicsContext&, const IntRect& dirtyRect) final;

    void drawSettings(GraphicsContext&);

    bool mouseEvent(PageOverlay&, const PlatformMouseEvent&) final;

    FloatRect rectForSettingAtIndex(unsigned) const;
    bool valueForSetting(ASCIILiteral) const;

    std::optional<std::pair<RenderLayer&, GraphicsLayer&>> activeLayer() const;
    std::optional<InteractionRegion> activeRegion() const;

    bool shouldPaintOverlayIntoLayer() const override { return valueForSetting("regions"_s); }

    struct Setting {
        ASCIILiteral key;
        ASCIILiteral name;
        bool value { false };
    };    

    FixedVector<Setting> m_settings {
        { "constrain"_s, "Constrain to Regions"_s, true },
        { "clip"_s, "Clip to Regions"_s, true },
        { "wash"_s, "Draw Wash"_s, false },
        { "contextualColor"_s, "Contextual Color"_s, true },
        { "contextualSize"_s, "Contextual Size"_s, true },
        { "cursor"_s, "Show Cursor"_s, true },
        { "hover"_s, "CSS Hover"_s, false },
        { "regions"_s, "Show Regions"_s, false }
    };

    IntPoint m_mouseLocationInContentCoordinates;
};

bool InteractionRegionOverlay::updateRegion()
{
    m_overlay->setNeedsDisplay();
    return true;
}

static Vector<Path> pathsForRegion(const Region& region, float borderRadius)
{
    static constexpr float radius = 4;

    Vector<FloatRect> rects = region.rects().map([] (auto rect) -> FloatRect {
        return rect;
    });
    return PathUtilities::pathsWithShrinkWrappedRects(rects, std::max(borderRadius, radius));
}

std::optional<std::pair<RenderLayer&, GraphicsLayer&>> InteractionRegionOverlay::activeLayer() const
{
    constexpr OptionSet<HitTestRequest::Type> hitType {
        HitTestRequest::Type::ReadOnly,
        HitTestRequest::Type::Active,
        HitTestRequest::Type::AllowChildFrameContent
    };
    HitTestResult result(m_mouseLocationInContentCoordinates);
    m_page.mainFrame().document()->hitTest(hitType, result);

    auto* hitNode = result.innerNode();
    if (!hitNode || !hitNode->renderer())
        return std::nullopt;

    auto* rendererLayer = hitNode->renderer()->enclosingLayer();
    if (!rendererLayer)
        return std::nullopt;

    auto* layer = rendererLayer->enclosingCompositingLayerForRepaint().layer;
    if (!layer)
        return std::nullopt;

    auto* backing = layer->backing();
    if (!backing)
        return std::nullopt;

    auto* graphicsLayer = backing->graphicsLayer();
    if (!graphicsLayer)
        return std::nullopt;

    return { { *layer, *graphicsLayer } };
}

std::optional<InteractionRegion> InteractionRegionOverlay::activeRegion() const
{
#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
    auto layerPair = activeLayer();
    if (!layerPair)
        return std::nullopt;
    auto& [layer, graphicsLayer] = *layerPair;

    std::optional<InteractionRegion> hitRegion;
    Region hitRegionInOverlayCoordinates;
    float hitRegionArea = 0;

    auto regions = graphicsLayer.eventRegion().interactionRegions();
    for (const auto& region : regions) {
        float area = 0;
        FloatRect boundingRect;
        Region regionInOverlayCoordinates;

        for (auto rect : region.regionInLayerCoordinates.rects()) {
            rect.move(roundedIntSize(graphicsLayer.offsetFromRenderer()));
            IntRect rectInOverlayCoordinates = layer.renderer().localToAbsoluteQuad(FloatRect { rect }).enclosingBoundingBox();
            if (boundingRect.isEmpty())
                boundingRect = rectInOverlayCoordinates;
            else
                boundingRect.unite(rectInOverlayCoordinates);
            area += rectInOverlayCoordinates.area();
            regionInOverlayCoordinates.unite(rectInOverlayCoordinates);
        }

        if (!boundingRect.contains(m_mouseLocationInContentCoordinates))
            continue;

        auto paths = pathsForRegion(regionInOverlayCoordinates, region.borderRadius);
        bool didHitRegion = false;
        for (const auto& path : paths) {
            if (path.contains(m_mouseLocationInContentCoordinates)) {
                didHitRegion = true;
                break;
            }
        }
        
        if (!didHitRegion)
            continue;

        if (area > m_page.mainFrame().view()->layoutSize().area() / 2)
            continue;

        if (didHitRegion && (!hitRegion || area < hitRegionArea)) {
            hitRegion = region;
            hitRegionArea = area;
            hitRegionInOverlayCoordinates = regionInOverlayCoordinates;
        }
    }
    
    if (hitRegion)
        hitRegion->regionInLayerCoordinates = hitRegionInOverlayCoordinates;

    return hitRegion;
#else
    return std::nullopt;
#endif
}

static void drawCheckbox(const String& text, GraphicsContext& context, const FontCascade& font, const FloatRect& box, bool state)
{
    static constexpr float lineHeight = 14;
    static constexpr float checkboxVerticalPadding = 2;
    static constexpr float textHorizontalPadding = 4;

    FloatRect checkboxRect { box.location() + FloatSize { 0, checkboxVerticalPadding }, FloatSize { lineHeight, lineHeight } };

    TextRun textRun = TextRun(text);
    context.setFillColor(Color::black);
    context.drawText(font, textRun, box.location() + FloatSize { checkboxRect.width() + textHorizontalPadding, lineHeight });

    Path checkboxPath;
    checkboxPath.addRoundedRect(FloatRoundedRect { checkboxRect, FloatRoundedRect::Radii { 3 } });

    if (state) {
        context.setFillColor(Color::darkGray);
        context.fillPath(checkboxPath);
    }

    context.setStrokeColor(Color::black.colorWithAlphaByte(127));
    context.setStrokeThickness(1);
    context.strokePath(checkboxPath);
}

FloatRect InteractionRegionOverlay::rectForSettingAtIndex(unsigned index) const
{
    auto viewSize = m_page.mainFrame().view()->layoutSize();
    static constexpr float settingsWidth = 150;
    static constexpr float rowHeight = 16;
    return {
        FloatPoint { viewSize.width() - settingsWidth - 14, 10 }
            + FloatSize { 4, rowHeight * index + 2 },
        FloatSize { settingsWidth, rowHeight }
    };
}

bool InteractionRegionOverlay::valueForSetting(ASCIILiteral name) const
{
    for (const auto& setting : m_settings) {
        if (name == setting.key)
            return setting.value;
    }

    ASSERT_NOT_REACHED();
    return false;
}

void InteractionRegionOverlay::drawSettings(GraphicsContext& context)
{
    GraphicsContextStateSaver stateSaver(context);

    FloatRect rect = rectForSettingAtIndex(0);
    for (unsigned i = 1; i < m_settings.size(); i++)
        rect.unite(rectForSettingAtIndex(i));

    rect.expand(FloatBoxExtent { 4, 4, 4, 4 });

    {
        GraphicsContextStateSaver stateSaver(context);
        context.setShadow({ }, 5, Color(Color::black).colorWithAlpha(0.5));
        context.fillRoundedRect(FloatRoundedRect { rect, FloatRoundedRect::Radii { 6 } }, Color(Color::white).colorWithAlpha(0.85));
    }

    FontCascadeDescription fontDescription;
    fontDescription.setOneFamily("Helvetica"_s);
    fontDescription.setSpecifiedSize(12);
    fontDescription.setComputedSize(12);
    fontDescription.setWeight(FontSelectionValue(500));
    FontCascade font(WTFMove(fontDescription), 0, 0);
    font.update(nullptr);

    for (unsigned i = 0; i < m_settings.size(); i++) {
        const auto& setting = m_settings[i];
        drawCheckbox(setting.name, context, font, rectForSettingAtIndex(i), setting.value);
    }
}

void InteractionRegionOverlay::drawRect(PageOverlay&, GraphicsContext& context, const IntRect& dirtyRect)
{
    GraphicsContextStateSaver stateSaver(context);
    
    context.clearRect(dirtyRect);

    auto region = activeRegion();

    if (region || !valueForSetting("constrain"_s)) {
        auto gradientData = [&] (float radius) {
            Gradient::RadialData gradientData;
            gradientData.point0 = m_mouseLocationInContentCoordinates;
            gradientData.point1 = m_mouseLocationInContentCoordinates;
            gradientData.startRadius = 0;
            gradientData.endRadius = radius;
            gradientData.aspectRatio = 1;
            return gradientData;
        };

        auto makeGradient = [&] (bool hasLightBackground, Gradient::RadialData gradientData) {
            auto gradient = Gradient::create(WTFMove(gradientData), { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied });
            if (region && valueForSetting("wash"_s) && valueForSetting("clip"_s)) {
                gradient->addColorStop({ 0.1, Color(Color::white).colorWithAlpha(0.5) });
                gradient->addColorStop({ 1, hasLightBackground ? Color(Color::black).colorWithAlpha(0.05) : Color(Color::white).colorWithAlpha(0.1) });
            } else if (!valueForSetting("clip"_s) || !valueForSetting("constrain"_s)) {
                gradient->addColorStop({ 0.1, Color(Color::white).colorWithAlpha(0.2) });
                gradient->addColorStop({ 1, Color(Color::white).colorWithAlpha(0) });
            } else {
                gradient->addColorStop({ 0.1, Color(Color::white).colorWithAlpha(0.5) });
                gradient->addColorStop({ 1, Color(Color::white).colorWithAlpha(0) });
            }

            return gradient;
        };
        
        constexpr float defaultRadius = 50;
        bool shouldClip = valueForSetting("clip"_s);
        Vector<Path> clipPaths;

        if (shouldClip)
            clipPaths = pathsForRegion(region->regionInLayerCoordinates, region->borderRadius);

        bool shouldUseBackdropGradient = !shouldClip || !region || (!valueForSetting("wash"_s) && valueForSetting("clip"_s));

        if (shouldUseBackdropGradient) {
            if (shouldClip) {
                for (const auto& path : clipPaths) {
                    float radius = valueForSetting("contextualSize"_s) ? 1.5 * path.boundingRect().size().minDimension() : defaultRadius;
                    auto backdropGradient = Gradient::create(gradientData(radius * 1.5), { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied });
                    backdropGradient->addColorStop({ 0.1, Color(Color::black).colorWithAlpha(0.2) });
                    backdropGradient->addColorStop({ 1, Color(Color::black).colorWithAlpha(0) });

                    context.setFillGradient(WTFMove(backdropGradient));
                    context.fillPath(path);
                }
            } else {
                auto backdropGradient = Gradient::create(gradientData(defaultRadius * 2), { ColorInterpolationMethod::SRGB { }, AlphaPremultiplication::Unpremultiplied });
                backdropGradient->addColorStop({ 0.1, Color(Color::black).colorWithAlpha(0.2) });
                backdropGradient->addColorStop({ 1, Color(Color::black).colorWithAlpha(0) });

                context.setFillGradient(WTFMove(backdropGradient));
                context.fillRect(dirtyRect);    
            }
        }

        bool hasLightBackground = false;
        if (!shouldUseBackdropGradient && valueForSetting("contextualColor"_s))
            hasLightBackground = region->hasLightBackground;

        if (shouldClip) {
            for (const auto& path : clipPaths) {
                float radius = valueForSetting("contextualSize"_s) ? 1.5 * path.boundingRect().size().minDimension() : defaultRadius;
                context.setFillGradient(makeGradient(hasLightBackground, gradientData(radius)));
                context.fillPath(path);
            }
        } else {
            context.setFillGradient(makeGradient(hasLightBackground, gradientData(defaultRadius)));
            context.fillRect(dirtyRect);
        }
    }

    stateSaver.restore();

    drawSettings(context);
}

bool InteractionRegionOverlay::mouseEvent(PageOverlay& overlay, const PlatformMouseEvent& event)
{
    auto mainFrameView = m_page.mainFrame().view();

    std::optional<Cursor> cursorToSet;

    if (!valueForSetting("cursor"_s))
        cursorToSet = noneCursor();
    else if (!valueForSetting("hover"_s))
        cursorToSet = pointerCursor();

    auto eventInContentsCoordinates = mainFrameView->windowToContents(event.position());
    for (unsigned i = 0; i < m_settings.size(); i++) {
        if (!rectForSettingAtIndex(i).contains(eventInContentsCoordinates))
            continue;
        cursorToSet = handCursor();
        if (event.button() == LeftButton && event.type() == PlatformEvent::MousePressed) {
            m_settings[i].value = !m_settings[i].value;
            m_page.forceRepaintAllFrames();
            return true;
        }
    }

    if (cursorToSet)
        mainFrameView->setCursor(*cursorToSet);

    m_mouseLocationInContentCoordinates = eventInContentsCoordinates;
    overlay.setNeedsDisplay();

    if (event.type() == PlatformEvent::MouseMoved && !event.buttons() && !valueForSetting("hover"_s))
        return true;

    return false;
}

#if COMPILER(CLANG)
#pragma mark - RegionOverlay
#endif

Ref<RegionOverlay> RegionOverlay::create(Page& page, DebugPageOverlays::RegionType regionType)
{
    switch (regionType) {
    case DebugPageOverlays::RegionType::WheelEventHandlers:
        return MouseWheelRegionOverlay::create(page);
    case DebugPageOverlays::RegionType::NonFastScrollableRegion:
        return NonFastScrollableRegionOverlay::create(page);
    case DebugPageOverlays::RegionType::InteractionRegion:
        return InteractionRegionOverlay::create(page);
    }
    ASSERT_NOT_REACHED();
    return MouseWheelRegionOverlay::create(page);
}

RegionOverlay::RegionOverlay(Page& page, Color regionColor)
    : m_page(page)
    , m_overlay(PageOverlay::create(*this, PageOverlay::OverlayType::Document))
    , m_color(regionColor)
{
}

RegionOverlay::~RegionOverlay()
{
    if (m_overlay)
        m_page.pageOverlayController().uninstallPageOverlay(*m_overlay, PageOverlay::FadeMode::DoNotFade);
}

void RegionOverlay::willMoveToPage(PageOverlay&, Page* page)
{
    if (!page)
        m_overlay = nullptr;
}

void RegionOverlay::didMoveToPage(PageOverlay&, Page* page)
{
    if (page)
        setRegionChanged();
}

void RegionOverlay::drawRect(PageOverlay&, GraphicsContext& context, const IntRect& dirtyRect)
{
    context.clearRect(dirtyRect);

    if (!m_region)
        return;

    drawRegion(context, *m_region, m_color, dirtyRect);
}

void RegionOverlay::drawRegion(GraphicsContext& context, const Region& region, const Color& color, const IntRect& dirtyRect)
{
    GraphicsContextStateSaver saver(context);
    context.setFillColor(color);
    for (auto rect : region.rects()) {
        if (rect.intersects(dirtyRect))
            context.fillRect(rect);
    }
}

bool RegionOverlay::mouseEvent(PageOverlay&, const PlatformMouseEvent&)
{
    return false;
}

void RegionOverlay::didScrollFrame(PageOverlay&, Frame&)
{
}

void RegionOverlay::recomputeRegion()
{
    if (!m_regionChanged)
        return;

    if (updateRegion())
        m_overlay->setNeedsDisplay();

    m_regionChanged = false;
}

#if COMPILER(CLANG)
#pragma mark - DebugPageOverlays
#endif

DebugPageOverlays& DebugPageOverlays::singleton()
{
    if (!sharedDebugOverlays)
        sharedDebugOverlays = new DebugPageOverlays;

    return *sharedDebugOverlays;
}

static inline size_t indexOf(DebugPageOverlays::RegionType regionType)
{
    return static_cast<size_t>(regionType);
}

RegionOverlay& DebugPageOverlays::ensureRegionOverlayForPage(Page& page, RegionType regionType)
{
    auto it = m_pageRegionOverlays.find(&page);
    if (it != m_pageRegionOverlays.end()) {
        auto& visualizer = it->value[indexOf(regionType)];
        if (!visualizer)
            visualizer = RegionOverlay::create(page, regionType);
        return *visualizer;
    }

    Vector<RefPtr<RegionOverlay>> visualizers(NumberOfRegionTypes);
    auto visualizer = RegionOverlay::create(page, regionType);
    visualizers[indexOf(regionType)] = visualizer.copyRef();
    m_pageRegionOverlays.add(&page, WTFMove(visualizers));
    return visualizer;
}

void DebugPageOverlays::showRegionOverlay(Page& page, RegionType regionType)
{
    auto& visualizer = ensureRegionOverlayForPage(page, regionType);
    page.pageOverlayController().installPageOverlay(visualizer.overlay(), PageOverlay::FadeMode::DoNotFade);
}

void DebugPageOverlays::hideRegionOverlay(Page& page, RegionType regionType)
{
    auto it = m_pageRegionOverlays.find(&page);
    if (it == m_pageRegionOverlays.end())
        return;
    auto& visualizer = it->value[indexOf(regionType)];
    if (!visualizer)
        return;
    page.pageOverlayController().uninstallPageOverlay(visualizer->overlay(), PageOverlay::FadeMode::DoNotFade);
    visualizer = nullptr;
}

void DebugPageOverlays::regionChanged(Frame& frame, RegionType regionType)
{
    auto* page = frame.page();
    if (!page)
        return;

    if (auto* visualizer = regionOverlayForPage(*page, regionType))
        visualizer->setRegionChanged();
}

void DebugPageOverlays::updateRegionIfNecessary(Page& page, RegionType regionType)
{
    if (auto* visualizer = regionOverlayForPage(page, regionType))
        visualizer->recomputeRegion();
}

RegionOverlay* DebugPageOverlays::regionOverlayForPage(Page& page, RegionType regionType) const
{
    auto it = m_pageRegionOverlays.find(&page);
    if (it == m_pageRegionOverlays.end())
        return nullptr;
    return it->value.at(indexOf(regionType)).get();
}

void DebugPageOverlays::updateOverlayRegionVisibility(Page& page, OptionSet<DebugOverlayRegions> visibleRegions)
{
    if (visibleRegions.contains(DebugOverlayRegions::NonFastScrollableRegion))
        showRegionOverlay(page, RegionType::NonFastScrollableRegion);
    else
        hideRegionOverlay(page, RegionType::NonFastScrollableRegion);

    if (visibleRegions.contains(DebugOverlayRegions::WheelEventHandlerRegion))
        showRegionOverlay(page, RegionType::WheelEventHandlers);
    else
        hideRegionOverlay(page, RegionType::WheelEventHandlers);
    
    if (visibleRegions.contains(DebugOverlayRegions::InteractionRegion))
        showRegionOverlay(page, RegionType::InteractionRegion);
    else
        hideRegionOverlay(page, RegionType::InteractionRegion);
}

void DebugPageOverlays::settingsChanged(Page& page)
{
    auto activeOverlayRegions = OptionSet<DebugOverlayRegions>::fromRaw(page.settings().visibleDebugOverlayRegions());
    if (!activeOverlayRegions && !hasOverlays(page))
        return;

    DebugPageOverlays::singleton().updateOverlayRegionVisibility(page, activeOverlayRegions);
}

bool DebugPageOverlays::shouldPaintOverlayIntoLayer(Page& page, RegionType regionType) const
{
    if (auto* overlay = regionOverlayForPage(page, regionType))
        return overlay->shouldPaintOverlayIntoLayer();
    return false;
}

}
