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

#import "config.h"
#import "ServicesOverlayController.h"

#if (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) && PLATFORM(MAC)

#import "Chrome.h"
#import "ChromeClient.h"
#import "Document.h"
#import "Editor.h"
#import "EventHandler.h"
#import "FloatQuad.h"
#import "FocusController.h"
#import "Frame.h"
#import "FrameSelection.h"
#import "FrameView.h"
#import "GapRects.h"
#import "GraphicsContext.h"
#import "GraphicsLayer.h"
#import "GraphicsLayerCA.h"
#import "Logging.h"
#import "Page.h"
#import "PageOverlayController.h"
#import "PlatformCAAnimationCocoa.h"
#import "Settings.h"
#import <QuartzCore/QuartzCore.h>
#import <pal/spi/mac/DataDetectorsSPI.h>
#import <wtf/SoftLinking.h>

const float highlightFadeAnimationDuration = 0.3;

namespace WebCore {

Ref<ServicesOverlayController::Highlight> ServicesOverlayController::Highlight::createForSelection(ServicesOverlayController& controller, RetainPtr<DDHighlightRef>&& ddHighlight, SimpleRange&& range)
{
    return adoptRef(*new Highlight(controller, Highlight::SelectionType, WTFMove(ddHighlight), WTFMove(range)));
}

Ref<ServicesOverlayController::Highlight> ServicesOverlayController::Highlight::createForTelephoneNumber(ServicesOverlayController& controller, RetainPtr<DDHighlightRef>&& ddHighlight, SimpleRange&& range)
{
    return adoptRef(*new Highlight(controller, Highlight::TelephoneNumberType, WTFMove(ddHighlight), WTFMove(range)));
}

ServicesOverlayController::Highlight::Highlight(ServicesOverlayController& controller, Type type, RetainPtr<DDHighlightRef>&& ddHighlight, SimpleRange&& range)
    : m_controller(&controller)
    , m_range(WTFMove(range))
    , m_graphicsLayer(GraphicsLayer::create(controller.page().chrome().client().graphicsLayerFactory(), *this))
    , m_type(type)
{
    ASSERT(ddHighlight);

    m_graphicsLayer->setDrawsContent(true);

    setDDHighlight(ddHighlight.get());

    // Set directly on the PlatformCALayer so that when we leave the 'from' value implicit
    // in our animations, we get the right initial value regardless of flush timing.
    downcast<GraphicsLayerCA>(layer()).platformCALayer()->setOpacity(0);

    controller.didCreateHighlight(this);
}

ServicesOverlayController::Highlight::~Highlight()
{
    if (m_controller)
        m_controller->willDestroyHighlight(this);
}

void ServicesOverlayController::Highlight::setDDHighlight(DDHighlightRef highlight)
{
    if (!DataDetectorsLibrary())
        return;

    if (!m_controller)
        return;

    m_ddHighlight = highlight;

    if (!m_ddHighlight)
        return;

    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(m_ddHighlight.get());
    m_graphicsLayer->setPosition(FloatPoint(highlightBoundingRect.origin));
    m_graphicsLayer->setSize(FloatSize(highlightBoundingRect.size));

    m_graphicsLayer->setNeedsDisplay();
}

void ServicesOverlayController::Highlight::invalidate()
{
    layer().removeFromParent();
    m_controller = nullptr;
}

void ServicesOverlayController::Highlight::notifyFlushRequired(const GraphicsLayer*)
{
    if (!m_controller)
        return;

    m_controller->page().renderingUpdateScheduler().scheduleTimedRenderingUpdate();
}

void ServicesOverlayController::Highlight::paintContents(const GraphicsLayer*, GraphicsContext& graphicsContext, const FloatRect&, GraphicsLayerPaintBehavior)
{
    if (!DataDetectorsLibrary())
        return;

    CGContextRef cgContext = graphicsContext.platformContext();

    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    CGLayerRef highlightLayer = DDHighlightGetLayerWithContext(ddHighlight(), cgContext);
    ALLOW_DEPRECATED_DECLARATIONS_END
    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(ddHighlight());
    highlightBoundingRect.origin = CGPointZero;

    CGContextDrawLayerInRect(cgContext, highlightBoundingRect, highlightLayer);
}

float ServicesOverlayController::Highlight::deviceScaleFactor() const
{
    if (!m_controller)
        return 1;

    return m_controller->page().deviceScaleFactor();
}

void ServicesOverlayController::Highlight::fadeIn()
{
    RetainPtr<CABasicAnimation> animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    [animation setDuration:highlightFadeAnimationDuration];
    [animation setFillMode:kCAFillModeForwards];
    [animation setRemovedOnCompletion:false];
    [animation setToValue:@1];

    auto platformAnimation = PlatformCAAnimationCocoa::create(animation.get());
    downcast<GraphicsLayerCA>(layer()).platformCALayer()->addAnimationForKey("FadeHighlightIn", platformAnimation.get());
}

void ServicesOverlayController::Highlight::fadeOut()
{
    RetainPtr<CABasicAnimation> animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    [animation setDuration:highlightFadeAnimationDuration];
    [animation setFillMode:kCAFillModeForwards];
    [animation setRemovedOnCompletion:false];
    [animation setToValue:@0];

    RefPtr<Highlight> retainedSelf = this;
    [CATransaction begin];
    [CATransaction setCompletionBlock:[retainedSelf] () {
        retainedSelf->didFinishFadeOutAnimation();
    }];

    auto platformAnimation = PlatformCAAnimationCocoa::create(animation.get());
    downcast<GraphicsLayerCA>(layer()).platformCALayer()->addAnimationForKey("FadeHighlightOut", platformAnimation.get());
    [CATransaction commit];
}

void ServicesOverlayController::Highlight::didFinishFadeOutAnimation()
{
    if (!m_controller)
        return;

    if (m_controller->activeHighlight() == this)
        return;

    layer().removeFromParent();
}

ServicesOverlayController::ServicesOverlayController(Page& page)
    : m_page(page)
    , m_determineActiveHighlightTimer(*this, &ServicesOverlayController::determineActiveHighlightTimerFired)
    , m_buildHighlightsTimer(*this, &ServicesOverlayController::buildPotentialHighlightsIfNeeded)
{
}

ServicesOverlayController::~ServicesOverlayController()
{
    for (auto& highlight : m_highlights)
        highlight->invalidate();
}

void ServicesOverlayController::willMoveToPage(PageOverlay&, Page* page)
{
    if (page)
        return;

    ASSERT(m_servicesOverlay);
    m_servicesOverlay = nullptr;
}

void ServicesOverlayController::didMoveToPage(PageOverlay&, Page*)
{
}

static const uint8_t AlignmentNone = 0;
static const uint8_t AlignmentLeft = 1 << 0;
static const uint8_t AlignmentRight = 1 << 1;

static void expandForGap(Vector<LayoutRect>& rects, uint8_t* alignments, const GapRects& gap)
{
    if (!gap.left().isEmpty()) {
        LayoutUnit leftEdge = gap.left().x();
        for (unsigned i = 0; i < rects.size(); ++i) {
            if (alignments[i] & AlignmentLeft)
                rects[i].shiftXEdgeTo(leftEdge);
        }
    }

    if (!gap.right().isEmpty()) {
        LayoutUnit rightEdge = gap.right().maxX();
        for (unsigned i = 0; i < rects.size(); ++i) {
            if (alignments[i] & AlignmentRight)
                rects[i].shiftMaxXEdgeTo(rightEdge);
        }
    }
}

static inline void stitchRects(Vector<LayoutRect>& rects)
{
    if (rects.size() <= 1)
        return;
    
    Vector<LayoutRect> newRects;
    
    // FIXME: Need to support vertical layout.
    // First stitch together all the rects on the first line of the selection.
    size_t indexFromStart = 0;
    LayoutUnit firstTop = rects[indexFromStart].y();
    LayoutRect& currentRect = rects[indexFromStart];
    while (indexFromStart < rects.size() && rects[indexFromStart].y() == firstTop)
        currentRect.unite(rects[indexFromStart++]);
    
    newRects.append(currentRect);
    if (indexFromStart == rects.size()) {
        // All the rects are on one line. There is nothing else to do.
        rects.swap(newRects);
        return;
    }
    
    // Next stitch together all the rects on the last line of the selection.
    size_t indexFromEnd = rects.size() - 1;
    LayoutUnit lastTop = rects[indexFromEnd].y();
    LayoutRect lastRect = rects[indexFromEnd];
    while (indexFromEnd >= indexFromStart && rects[indexFromEnd].y() == lastTop)
        lastRect.unite(rects[indexFromEnd--]);
    
    // indexFromStart is the index of the first rectangle on the second line.
    // indexFromEnd is the index of the last rectangle on the second to the last line.
    // if they are equal, there is one additional rectangle for the line in the middle.
    if (indexFromEnd == indexFromStart)
        newRects.append(rects[indexFromStart]);
    
    if (indexFromEnd <= indexFromStart) {
        // There are no more rects to stitch. Just append the last line.
        newRects.append(lastRect);
        rects.swap(newRects);
        return;
    }
    
    // Stitch together all the rects after the first line until the second to the last included.
    currentRect = rects[indexFromStart];
    while (indexFromStart != indexFromEnd)
        currentRect.unite(rects[++indexFromStart]);
    
    newRects.append(currentRect);
    newRects.append(lastRect);

    rects.swap(newRects);
}

static void compactRectsWithGapRects(Vector<LayoutRect>& rects, const Vector<GapRects>& gapRects)
{
    stitchRects(rects);
    
    // FIXME: The following alignments are correct for LTR text.
    // We should also account for RTL.
    uint8_t alignments[3];
    if (rects.size() == 1) {
        alignments[0] = AlignmentLeft | AlignmentRight;
        alignments[1] = AlignmentNone;
        alignments[2] = AlignmentNone;
    } else if (rects.size() == 2) {
        alignments[0] = AlignmentRight;
        alignments[1] = AlignmentLeft;
        alignments[2] = AlignmentNone;
    } else {
        alignments[0] = AlignmentRight;
        alignments[1] = AlignmentLeft | AlignmentRight;
        alignments[2] = AlignmentLeft;
    }

    // Account for each GapRects by extending the edge of certain LayoutRects to meet the gap.
    for (auto& gap : gapRects)
        expandForGap(rects, alignments, gap);

    // If we have 3 rects we might need one final GapRects to align the edges.
    if (rects.size() == 3) {
        LayoutRect left;
        LayoutRect right;
        for (unsigned i = 0; i < 3; ++i) {
            if (alignments[i] & AlignmentLeft) {
                if (left.isEmpty())
                    left = rects[i];
                else if (rects[i].x() < left.x())
                    left = rects[i];
            }
            if (alignments[i] & AlignmentRight) {
                if (right.isEmpty())
                    right = rects[i];
                else if ((rects[i].x() + rects[i].width()) > (right.x() + right.width()))
                    right = rects[i];
            }
        }

        if (!left.isEmpty() || !right.isEmpty()) {
            GapRects gap;
            gap.uniteLeft(left);
            gap.uniteRight(right);
            expandForGap(rects, alignments, gap);
        }
    }
}

void ServicesOverlayController::selectionRectsDidChange(const Vector<LayoutRect>& rects, const Vector<GapRects>& gapRects, bool isTextOnly)
{
    m_currentSelectionRects = rects;
    m_isTextOnly = isTextOnly;

    m_lastSelectionChangeTime = MonotonicTime::now();

    compactRectsWithGapRects(m_currentSelectionRects, gapRects);

    // DataDetectors needs these reversed in order to place the arrow in the right location.
    m_currentSelectionRects.reverse();

    LOG(Services, "ServicesOverlayController - Selection rects changed - Now have %lu\n", rects.size());
    invalidateHighlightsOfType(Highlight::SelectionType);
}

void ServicesOverlayController::selectedTelephoneNumberRangesChanged()
{
    LOG(Services, "ServicesOverlayController - Telephone number ranges changed\n");
    invalidateHighlightsOfType(Highlight::TelephoneNumberType);
}

void ServicesOverlayController::invalidateHighlightsOfType(Highlight::Type type)
{
    if (!m_page.settings().serviceControlsEnabled())
        return;

    m_dirtyHighlightTypes |= type;
    m_buildHighlightsTimer.startOneShot(0_s);
}

void ServicesOverlayController::buildPotentialHighlightsIfNeeded()
{
    if (!m_dirtyHighlightTypes)
        return;

    if (m_dirtyHighlightTypes & Highlight::TelephoneNumberType)
        buildPhoneNumberHighlights();

    if (m_dirtyHighlightTypes & Highlight::SelectionType)
        buildSelectionHighlight();

    m_dirtyHighlightTypes = 0;

    if (m_potentialHighlights.isEmpty()) {
        if (m_servicesOverlay)
            m_page.pageOverlayController().uninstallPageOverlay(*m_servicesOverlay, PageOverlay::FadeMode::DoNotFade);
        return;
    }

    if (telephoneNumberRangesForFocusedFrame().isEmpty() && !hasRelevantSelectionServices())
        return;

    createOverlayIfNeeded();

    bool mouseIsOverButton;
    determineActiveHighlight(mouseIsOverButton);
}

bool ServicesOverlayController::mouseIsOverHighlight(Highlight& highlight, bool& mouseIsOverButton) const
{
    if (!DataDetectorsLibrary())
        return false;

    Boolean onButton;
    bool hovered = DDHighlightPointIsOnHighlight(highlight.ddHighlight(), (CGPoint)m_mousePosition, &onButton);
    mouseIsOverButton = onButton;
    return hovered;
}

Seconds ServicesOverlayController::remainingTimeUntilHighlightShouldBeShown(Highlight* highlight) const
{
    if (!highlight)
        return 0_s;

    Seconds minimumTimeUntilHighlightShouldBeShown = 200_ms;
    if (m_page.focusController().focusedOrMainFrame().selection().selection().isContentEditable())
        minimumTimeUntilHighlightShouldBeShown = 1_s;

    bool mousePressed = mainFrame().eventHandler().mousePressed();

    // Highlight hysteresis is only for selection services, because telephone number highlights are already much more stable
    // by virtue of being expanded to include the entire telephone number. However, we will still avoid highlighting
    // telephone numbers while the mouse is down.
    if (highlight->type() == Highlight::TelephoneNumberType)
        return mousePressed ? minimumTimeUntilHighlightShouldBeShown : 0_s;

    MonotonicTime now = MonotonicTime::now();
    Seconds timeSinceLastSelectionChange = now - m_lastSelectionChangeTime;
    Seconds timeSinceHighlightBecameActive = now - m_nextActiveHighlightChangeTime;
    Seconds timeSinceLastMouseUp = mousePressed ? 0_s : now - m_lastMouseUpTime;

    return minimumTimeUntilHighlightShouldBeShown - std::min(std::min(timeSinceLastSelectionChange, timeSinceHighlightBecameActive), timeSinceLastMouseUp);
}

void ServicesOverlayController::determineActiveHighlightTimerFired()
{
    bool mouseIsOverButton;
    determineActiveHighlight(mouseIsOverButton);
}

void ServicesOverlayController::drawRect(PageOverlay&, GraphicsContext&, const IntRect&)
{
}

void ServicesOverlayController::clearActiveHighlight()
{
    if (!m_activeHighlight)
        return;

    if (m_currentMouseDownOnButtonHighlight == m_activeHighlight)
        m_currentMouseDownOnButtonHighlight = nullptr;
    m_activeHighlight = nullptr;
}

void ServicesOverlayController::removeAllPotentialHighlightsOfType(Highlight::Type type)
{
    Vector<RefPtr<Highlight>> highlightsToRemove;
    for (auto& highlight : m_potentialHighlights) {
        if (highlight->type() == type)
            highlightsToRemove.append(highlight);
    }

    while (!highlightsToRemove.isEmpty())
        m_potentialHighlights.remove(highlightsToRemove.takeLast());
}

void ServicesOverlayController::buildPhoneNumberHighlights()
{
    Vector<SimpleRange> phoneNumberRanges;
    for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
        phoneNumberRanges.appendVector(frame->editor().detectedTelephoneNumberRanges());

    if (phoneNumberRanges.isEmpty()) {
        removeAllPotentialHighlightsOfType(Highlight::TelephoneNumberType);
        return;
    }

    if (!DataDetectorsLibrary())
        return;

    HashSet<RefPtr<Highlight>> newPotentialHighlights;

    FrameView& mainFrameView = *mainFrame().view();

    for (auto& range : phoneNumberRanges) {
        // FIXME: This makes a big rect if the range extends from the end of one line to the start of the next. Handle that case better?
        auto rect = enclosingIntRect(unitedBoundingBoxes(RenderObject::absoluteTextQuads(range)));

        // Convert to the main document's coordinate space.
        // FIXME: It's a little crazy to call contentsToWindow and then windowToContents in order to get the right coordinate space.
        // We should consider adding conversion functions to ScrollView for contentsToDocument(). Right now, contentsToRootView() is
        // not equivalent to what we need when you have a topContentInset or a header banner.
        auto* viewForRange = range.start.document().view();
        if (!viewForRange)
            continue;

        rect.setLocation(mainFrameView.windowToContents(viewForRange->contentsToWindow(rect.location())));

        CGRect cgRect = rect;
#if HAVE(DD_HIGHLIGHT_CREATE_WITH_SCALE)
        auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleScaleAndDirection(nullptr, &cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightStyleBubbleStandard | DDHighlightStyleStandardIconArrow, YES, NSWritingDirectionNatural, NO, YES, 0));
#else
        auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightStyleBubbleStandard | DDHighlightStyleStandardIconArrow, YES, NSWritingDirectionNatural, NO, YES));
#endif
        newPotentialHighlights.add(Highlight::createForTelephoneNumber(*this, WTFMove(ddHighlight), WTFMove(range)));
    }

    replaceHighlightsOfTypePreservingEquivalentHighlights(newPotentialHighlights, Highlight::TelephoneNumberType);
}

void ServicesOverlayController::buildSelectionHighlight()
{
    if (m_currentSelectionRects.isEmpty()) {
        removeAllPotentialHighlightsOfType(Highlight::SelectionType);
        return;
    }

    if (!DataDetectorsLibrary())
        return;

    HashSet<RefPtr<Highlight>> newPotentialHighlights;

    Vector<CGRect> cgRects;
    cgRects.reserveCapacity(m_currentSelectionRects.size());

    if (auto selectionRange = m_page.selection().firstRange()) {
        FrameView* mainFrameView = mainFrame().view();
        if (!mainFrameView)
            return;

        auto viewForRange = makeRefPtr(selectionRange->start.document().view());
        if (!viewForRange)
            return;

        for (auto& rect : m_currentSelectionRects) {
            IntRect currentRect = snappedIntRect(rect);
            currentRect.setLocation(mainFrameView->windowToContents(viewForRange->contentsToWindow(currentRect.location())));
            cgRects.append(currentRect);
        }

        if (!cgRects.isEmpty()) {
            CGRect visibleRect = mainFrameView->visibleContentRect();
#if HAVE(DD_HIGHLIGHT_CREATE_WITH_SCALE)
            auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleScaleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightStyleBubbleNone | DDHighlightStyleStandardIconArrow | DDHighlightStyleButtonShowAlways, YES, NSWritingDirectionNatural, NO, YES, 0));
#else
            auto ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightStyleBubbleNone | DDHighlightStyleStandardIconArrow | DDHighlightStyleButtonShowAlways, YES, NSWritingDirectionNatural, NO, YES));
#endif
            newPotentialHighlights.add(Highlight::createForSelection(*this, WTFMove(ddHighlight), WTFMove(*selectionRange)));
        }
    }

    replaceHighlightsOfTypePreservingEquivalentHighlights(newPotentialHighlights, Highlight::SelectionType);
}

void ServicesOverlayController::replaceHighlightsOfTypePreservingEquivalentHighlights(HashSet<RefPtr<Highlight>>& newPotentialHighlights, Highlight::Type type)
{
    // If any old Highlights are equivalent (by Range) to a new Highlight, reuse the old
    // one so that any metadata is retained.
    HashSet<RefPtr<Highlight>> reusedPotentialHighlights;

    for (auto& oldHighlight : m_potentialHighlights) {
        if (oldHighlight->type() != type)
            continue;

        for (auto& newHighlight : newPotentialHighlights) {
            if (highlightsAreEquivalent(oldHighlight.get(), newHighlight.get())) {
                oldHighlight->setDDHighlight(newHighlight->ddHighlight());

                reusedPotentialHighlights.add(oldHighlight);
                newPotentialHighlights.remove(newHighlight);

                break;
            }
        }
    }

    removeAllPotentialHighlightsOfType(type);

    m_potentialHighlights.add(newPotentialHighlights.begin(), newPotentialHighlights.end());
    m_potentialHighlights.add(reusedPotentialHighlights.begin(), reusedPotentialHighlights.end());
}

bool ServicesOverlayController::hasRelevantSelectionServices()
{
    return m_page.chrome().client().hasRelevantSelectionServices(m_isTextOnly);
}

void ServicesOverlayController::createOverlayIfNeeded()
{
    if (m_servicesOverlay)
        return;

    if (!m_page.settings().serviceControlsEnabled())
        return;

    auto overlay = PageOverlay::create(*this, PageOverlay::OverlayType::Document);
    m_servicesOverlay = overlay.ptr();
    m_page.pageOverlayController().installPageOverlay(WTFMove(overlay), PageOverlay::FadeMode::DoNotFade);
}

Vector<SimpleRange> ServicesOverlayController::telephoneNumberRangesForFocusedFrame()
{
    return m_page.focusController().focusedOrMainFrame().editor().detectedTelephoneNumberRanges();
}

bool ServicesOverlayController::highlightsAreEquivalent(const Highlight* a, const Highlight* b)
{
    if (a == b)
        return true;
    if (!a || !b)
        return false;
    return a->type() == b->type() && a->range() == b->range();
}

ServicesOverlayController::Highlight* ServicesOverlayController::findTelephoneNumberHighlightContainingSelectionHighlight(Highlight& selectionHighlight)
{
    if (selectionHighlight.type() != Highlight::SelectionType)
        return nullptr;

    auto selectionRange = m_page.selection().toNormalizedRange();
    if (!selectionRange)
        return nullptr;

    for (auto& highlight : m_potentialHighlights) {
        if (highlight->type() == Highlight::TelephoneNumberType && createLiveRange(highlight->range())->contains(createLiveRange(*selectionRange)))
            return highlight.get();
    }

    return nullptr;
}

void ServicesOverlayController::determineActiveHighlight(bool& mouseIsOverActiveHighlightButton)
{
    buildPotentialHighlightsIfNeeded();

    mouseIsOverActiveHighlightButton = false;

    RefPtr<Highlight> newActiveHighlight;

    for (auto& highlight : m_potentialHighlights) {
        if (highlight->type() == Highlight::SelectionType) {
            // If we've already found a new active highlight, and it's
            // a telephone number highlight, prefer that over this selection highlight.
            if (newActiveHighlight && newActiveHighlight->type() == Highlight::TelephoneNumberType)
                continue;

            // If this highlight has no compatible services, it can't be active.
            if (!hasRelevantSelectionServices())
                continue;
        }

        // If this highlight isn't hovered, it can't be active.
        bool mouseIsOverButton;
        if (!mouseIsOverHighlight(*highlight, mouseIsOverButton))
            continue;

        newActiveHighlight = highlight;
        mouseIsOverActiveHighlightButton = mouseIsOverButton;
    }

    // If our new active highlight is a selection highlight that is completely contained
    // by one of the phone number highlights, we'll make the phone number highlight active even if it's not hovered.
    if (newActiveHighlight && newActiveHighlight->type() == Highlight::SelectionType) {
        if (Highlight* containedTelephoneNumberHighlight = findTelephoneNumberHighlightContainingSelectionHighlight(*newActiveHighlight)) {
            newActiveHighlight = containedTelephoneNumberHighlight;

            // We will always initially choose the telephone number highlight over the selection highlight if the
            // mouse is over the telephone number highlight's button, so we know that it's not hovered if we got here.
            mouseIsOverActiveHighlightButton = false;
        }
    }

    if (!this->highlightsAreEquivalent(m_activeHighlight.get(), newActiveHighlight.get())) {
        // When transitioning to a new highlight, we might end up in determineActiveHighlight multiple times
        // before the new highlight actually becomes active. Keep track of the last next-but-not-yet-active
        // highlight, and only reset the active highlight hysteresis when that changes.
        if (m_nextActiveHighlight != newActiveHighlight) {
            m_nextActiveHighlight = newActiveHighlight;
            m_nextActiveHighlightChangeTime = MonotonicTime::now();
        }

        m_currentMouseDownOnButtonHighlight = nullptr;

        if (m_activeHighlight) {
            m_activeHighlight->fadeOut();
            m_activeHighlight = nullptr;
        }

        auto remainingTimeUntilHighlightShouldBeShown = this->remainingTimeUntilHighlightShouldBeShown(newActiveHighlight.get());
        if (remainingTimeUntilHighlightShouldBeShown > 0_s) {
            m_determineActiveHighlightTimer.startOneShot(remainingTimeUntilHighlightShouldBeShown);
            return;
        }

        m_activeHighlight = WTFMove(m_nextActiveHighlight);

        if (m_activeHighlight) {
            Ref<GraphicsLayer> highlightLayer = m_activeHighlight->layer();
            m_servicesOverlay->layer().addChild(WTFMove(highlightLayer));
            m_activeHighlight->fadeIn();
        }
    }
}

bool ServicesOverlayController::mouseEvent(PageOverlay&, const PlatformMouseEvent& event)
{
    m_mousePosition = mainFrame().view()->windowToContents(event.position());

    bool mouseIsOverActiveHighlightButton = false;
    determineActiveHighlight(mouseIsOverActiveHighlightButton);

    // Cancel the potential click if any button other than the left button changes state, and ignore the event.
    if (event.button() != MouseButton::LeftButton) {
        m_currentMouseDownOnButtonHighlight = nullptr;
        return false;
    }

    // If the mouse lifted while still over the highlight button that it went down on, then that is a click.
    if (event.type() == PlatformEvent::MouseReleased) {
        RefPtr<Highlight> mouseDownHighlight = m_currentMouseDownOnButtonHighlight;
        m_currentMouseDownOnButtonHighlight = nullptr;

        m_lastMouseUpTime = MonotonicTime::now();

        if (mouseIsOverActiveHighlightButton && mouseDownHighlight) {
            handleClick(m_mousePosition, *mouseDownHighlight);
            return true;
        }
        
        return false;
    }

    // If the mouse moved outside of the button tracking a potential click, stop tracking the click.
    if (event.type() == PlatformEvent::MouseMoved) {
        if (m_currentMouseDownOnButtonHighlight && mouseIsOverActiveHighlightButton)
            return true;

        m_currentMouseDownOnButtonHighlight = nullptr;
        return false;
    }

    // If the mouse went down over the active highlight's button, track this as a potential click.
    if (event.type() == PlatformEvent::MousePressed) {
        if (m_activeHighlight && mouseIsOverActiveHighlightButton) {
            m_currentMouseDownOnButtonHighlight = m_activeHighlight;
            return true;
        }

        return false;
    }

    return false;
}

void ServicesOverlayController::didScrollFrame(PageOverlay&, Frame& frame)
{
    if (frame.isMainFrame())
        return;

    invalidateHighlightsOfType(Highlight::TelephoneNumberType);
    invalidateHighlightsOfType(Highlight::SelectionType);
    buildPotentialHighlightsIfNeeded();

    bool mouseIsOverActiveHighlightButton;
    determineActiveHighlight(mouseIsOverActiveHighlightButton);
}

void ServicesOverlayController::handleClick(const IntPoint& clickPoint, Highlight& highlight)
{
    FrameView* frameView = mainFrame().view();
    if (!frameView)
        return;

    IntPoint windowPoint = frameView->contentsToWindow(clickPoint);

    if (highlight.type() == Highlight::SelectionType) {
        auto telephoneNumberRanges = telephoneNumberRangesForFocusedFrame();
        Vector<String> selectedTelephoneNumbers;
        selectedTelephoneNumbers.reserveCapacity(telephoneNumberRanges.size());
        for (auto& range : telephoneNumberRanges)
            selectedTelephoneNumbers.append(plainText(range));

        m_page.chrome().client().handleSelectionServiceClick(m_page.focusController().focusedOrMainFrame().selection(), selectedTelephoneNumbers, windowPoint);
    } else if (highlight.type() == Highlight::TelephoneNumberType)
        m_page.chrome().client().handleTelephoneNumberClick(plainText(highlight.range()), windowPoint);
}

Frame& ServicesOverlayController::mainFrame() const
{
    return m_page.mainFrame();
}

void ServicesOverlayController::didCreateHighlight(Highlight* highlight)
{
    ASSERT(!m_highlights.contains(highlight));
    m_highlights.add(highlight);
}

void ServicesOverlayController::willDestroyHighlight(Highlight* highlight)
{
    ASSERT(m_highlights.contains(highlight));
    m_highlights.remove(highlight);
}

} // namespace WebKit

#endif // (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) && PLATFORM(MAC)
