/*
 * 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 "ElementIterator.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "Page.h"
#include "PageOverlay.h"
#include "PageOverlayController.h"
#include "Region.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; }

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&) final;
    void didScrollFrame(PageOverlay&, Frame&) final;

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 };
};

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
}

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<ComparableASCIILiteral, SRGBA<uint8_t>> colorMappings[] = {
        { "mousedown", { 80, 245, 80, 50 } },
        { "mousemove", { 245, 245, 80, 50 } },
        { "mouseup", { 80, 245, 176, 50 } },
        { "touchend", { 191, 63, 127, 50 } },
        { "touchforcechange", { 63, 63, 191, 50 } },
        { "touchmove", { 80, 204, 245, 50 } },
        { "touchstart", { 191, 191, 63, 50 } },
        { "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");
    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 = [&] (ASCIILiteral color) {
        drawLegend(colors.get(StringView { color }), color);
    };
    drawEventLegend("touchstart"_s);
    drawEventLegend("touchmove"_s);
    drawEventLegend("touchend"_s);
    drawEventLegend("touchforcechange"_s);
    drawLegend(m_color, "passive listeners"_s);
    drawEventLegend("mousedown"_s);
    drawEventLegend("mousemove"_s);
    drawEventLegend("mouseup"_s);
#else
    // On desktop platforms, the "wheel" region includes the non-fast scrollable region.
    drawLegend(colors.get("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);
}

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);
    }
    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;
}

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);
}

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

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

}
