/*
 * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "SelectionHandler.h"

#include "DOMSupport.h"
#include "Document.h"
#include "FatFingers.h"
#include "FloatQuad.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "FrameView.h"
#include "HitTestResult.h"
#include "InputHandler.h"
#include "IntRect.h"
#include "TouchEventHandler.h"
#include "WebPageClient.h"
#include "WebPage_p.h"
#include "WebSelectionOverlay.h"

#include "htmlediting.h"
#include "visible_units.h"

#include <BlackBerryPlatformKeyboardEvent.h>
#include <BlackBerryPlatformLog.h>

#include <sys/keycodes.h>

// Note: This generates a lot of logs when dumping rects lists. It will seriously
// impact performance. Do not enable this during performance tests.
#define SHOWDEBUG_SELECTIONHANDLER 0
#define SHOWDEBUG_SELECTIONHANDLER_TIMING 0

using namespace BlackBerry::Platform;
using namespace WebCore;

#if SHOWDEBUG_SELECTIONHANDLER
#define SelectionLog(severity, format, ...) logAlways(severity, format, ## __VA_ARGS__)
#else
#define SelectionLog(severity, format, ...)
#endif // SHOWDEBUG_SELECTIONHANDLER

#if SHOWDEBUG_SELECTIONHANDLER_TIMING
#define SelectionTimingLog(severity, format, ...) logAlways(severity, format, ## __VA_ARGS__)
#else
#define SelectionTimingLog(severity, format, ...)
#endif // SHOWDEBUG_SELECTIONHANDLER_TIMING

namespace BlackBerry {
namespace WebKit {

SelectionHandler::SelectionHandler(WebPagePrivate* page)
    : m_webPage(page)
    , m_selectionActive(false)
    , m_caretActive(false)
    , m_lastUpdatedEndPointIsValid(false)
    , m_didSuppressCaretPositionChangedNotification(false)
{
}

SelectionHandler::~SelectionHandler()
{
}

void SelectionHandler::cancelSelection()
{
    m_selectionActive = false;
    m_lastSelectionRegion = IntRectRegion();

    SelectionLog(LogLevelInfo, "SelectionHandler::cancelSelection");

    if (m_webPage->m_inputHandler->isInputMode())
        m_webPage->m_inputHandler->cancelSelection();
    else
        m_webPage->focusedOrMainFrame()->selection()->clear();
}

WebString SelectionHandler::selectedText() const
{
    return m_webPage->focusedOrMainFrame()->editor()->selectedText();
}

WebCore::IntRect SelectionHandler::clippingRectForVisibleContent() const
{
    // Get the containing content rect for the frame.
    Frame* frame = m_webPage->focusedOrMainFrame();
    WebCore::IntRect clipRect = WebCore::IntRect(WebCore::IntPoint(0, 0), m_webPage->contentsSize());
    if (frame != m_webPage->mainFrame()) {
        clipRect = m_webPage->getRecursiveVisibleWindowRect(frame->view(), true /* no clip to main frame window */);
        clipRect = m_webPage->m_mainFrame->view()->windowToContents(clipRect);
    }

    // Get the input field containing box.
    WebCore::IntRect inputBoundingBox = m_webPage->m_inputHandler->boundingBoxForInputField();
    if (!inputBoundingBox.isEmpty()) {
        // Adjust the bounding box to the frame offset.
        inputBoundingBox = m_webPage->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(inputBoundingBox));
        clipRect.intersect(inputBoundingBox);
    }
    return clipRect;
}

void SelectionHandler::regionForTextQuads(Vector<FloatQuad> &quadList, IntRectRegion& region, bool shouldClipToVisibleContent) const
{
    ASSERT(region.isEmpty());

    if (!quadList.isEmpty()) {
        FrameView* frameView = m_webPage->focusedOrMainFrame()->view();

        // frameRect is in frame coordinates.
        WebCore::IntRect frameRect(WebCore::IntPoint(0, 0), frameView->contentsSize());

        // framePosition is in main frame coordinates.
        WebCore::IntPoint framePosition = m_webPage->frameOffset(m_webPage->focusedOrMainFrame());

        // Get the visibile content rect.
        WebCore::IntRect clippingRect = shouldClipToVisibleContent ? clippingRectForVisibleContent() : WebCore::IntRect(-1, -1, 0, 0);

        // Convert the text quads into a more platform friendy
        // IntRectRegion and adjust for subframes.
        Platform::IntRect selectionBoundingBox;
        std::vector<Platform::IntRect> adjustedIntRects;
        for (unsigned i = 0; i < quadList.size(); i++) {
            WebCore::IntRect enclosingRect = quadList[i].enclosingBoundingBox();
            enclosingRect.intersect(frameRect);
            enclosingRect.move(framePosition.x(), framePosition.y());

            // Clip to the visible content.
            if (clippingRect.location() != DOMSupport::InvalidPoint)
                enclosingRect.intersect(clippingRect);

            adjustedIntRects.push_back(enclosingRect);
            selectionBoundingBox = unionOfRects(enclosingRect, selectionBoundingBox);
        }
        region = IntRectRegion(selectionBoundingBox, adjustedIntRects.size(), adjustedIntRects);
    }
}

static VisiblePosition visiblePositionForPointIgnoringClipping(const Frame& frame, const WebCore::IntPoint& framePoint)
{
    // Frame::visiblePositionAtPoint hard-codes ignoreClipping=false in the
    // call to hitTestResultAtPoint. This has a bug where some pages (such as
    // metafilter) will return the wrong VisiblePosition for points that are
    // outside the visible rect. To work around the bug, this is a copy of
    // visiblePositionAtPoint which which passes ignoreClipping=true.
    // See RIM Bug #4315.
    HitTestResult result = frame.eventHandler()->hitTestResultAtPoint(framePoint, true /* allowShadowContent */, true /* ignoreClipping */);

    Node* node = result.innerNode();
    if (!node || node->document() != frame.document())
        return VisiblePosition();

    RenderObject* renderer = node->renderer();
    if (!renderer)
        return VisiblePosition();

    VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
    if (visiblePos.isNull())
        visiblePos = VisiblePosition(Position(createLegacyEditingPosition(node, 0)));

    return visiblePos;
}

static unsigned short directionOfPointRelativeToRect(const WebCore::IntPoint& point, const WebCore::IntRect& rect, const bool useTopPadding = true, const bool useBottomPadding = true)
{
    ASSERT(!rect.contains(point));

    // Padding to prevent accidental trigger of up/down when intending to do horizontal movement.
    const int verticalPadding = 5;

    // Do height movement check first but add padding. We may be off on both x & y axis and only
    // want to move in one direction at a time.
    if (point.y() - (useTopPadding ? verticalPadding : 0) < rect.y())
        return KEYCODE_UP;
    if (point.y() > rect.maxY() + (useBottomPadding ? verticalPadding : 0))
        return KEYCODE_DOWN;
    if (point.x() < rect.location().x())
        return KEYCODE_LEFT;
    if (point.x() > rect.maxX())
        return KEYCODE_RIGHT;

    return 0;
}

bool SelectionHandler::shouldUpdateSelectionOrCaretForPoint(const WebCore::IntPoint& point, const WebCore::IntRect& caretRect, bool startCaret) const
{
    ASSERT(m_webPage->m_inputHandler->isInputMode());

    // If the point isn't valid don't block change as it is not actually changing.
    if (point == DOMSupport::InvalidPoint)
        return true;

    VisibleSelection currentSelection = m_webPage->focusedOrMainFrame()->selection()->selection();

    // If the input field is single line or we are on the first or last
    // line of a multiline input field only horizontal movement is supported.
    bool aboveCaret = point.y() < caretRect.y();
    bool belowCaret = point.y() >= caretRect.maxY();

    SelectionLog(LogLevelInfo, "SelectionHandler::shouldUpdateSelectionOrCaretForPoint multiline = %s above = %s below = %s first line = %s last line = %s start = %s"
            , m_webPage->m_inputHandler->isMultilineInputMode() ? "true" : "false", aboveCaret ? "true" : "false", belowCaret ? "true" : "false"
            , inSameLine(currentSelection.visibleStart(), startOfEditableContent(currentSelection.visibleStart())) ? "true" : "false"
            , inSameLine(currentSelection.visibleEnd(), endOfEditableContent(currentSelection.visibleEnd())) ? "true" : "false"
            , startCaret ? "true" : "false");

    if (!m_webPage->m_inputHandler->isMultilineInputMode() && (aboveCaret || belowCaret))
        return false;
    if (startCaret && inSameLine(currentSelection.visibleStart(), startOfEditableContent(currentSelection.visibleStart())) && aboveCaret)
        return false;
    if (!startCaret && inSameLine(currentSelection.visibleEnd(), endOfEditableContent(currentSelection.visibleEnd())) && belowCaret)
        return false;

    return true;
}

void SelectionHandler::setCaretPosition(const WebCore::IntPoint &position)
{
    if (!m_webPage->m_inputHandler->isInputMode())
        return;

    m_caretActive = true;

    SelectionLog(LogLevelInfo, "SelectionHandler::setCaretPosition requested point %d, %d", position.x(), position.y());

    Frame* focusedFrame = m_webPage->focusedOrMainFrame();
    FrameSelection* controller = focusedFrame->selection();
    WebCore::IntPoint relativePoint = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, position);
    WebCore::IntRect currentCaretRect = controller->selection().visibleStart().absoluteCaretBounds();

    if (relativePoint == DOMSupport::InvalidPoint || !shouldUpdateSelectionOrCaretForPoint(relativePoint, currentCaretRect)) {
        selectionPositionChanged(true /* forceUpdateWithoutChange */);
        return;
    }

    VisiblePosition visibleCaretPosition(focusedFrame->visiblePositionForPoint(relativePoint));

    if (!DOMSupport::isPositionInNode(m_webPage->focusedOrMainFrame()->document()->focusedNode(), visibleCaretPosition.deepEquivalent())) {
        if (unsigned short character = directionOfPointRelativeToRect(relativePoint, currentCaretRect))
            m_webPage->m_inputHandler->handleKeyboardInput(Platform::KeyboardEvent(character));

        // Send the selection changed in case this does not trigger a selection change to
        // ensure the caret position is accurate. This may be a duplicate event.
        selectionPositionChanged(true /* forceUpdateWithoutChange */);
        return;
    }

    VisibleSelection newSelection(visibleCaretPosition);
    if (controller->selection() == newSelection) {
        selectionPositionChanged(true /* forceUpdateWithoutChange */);
        return;
    }

    controller->setSelection(newSelection);

    SelectionLog(LogLevelInfo, "SelectionHandler::setCaretPosition point valid, cursor updated");
}

void SelectionHandler::inputHandlerDidFinishProcessingChange()
{
    if (m_didSuppressCaretPositionChangedNotification)
        notifyCaretPositionChangedIfNeeded();
}

// This function makes sure we are not reducing the selection to a caret selection.
static bool shouldExtendSelectionInDirection(const VisibleSelection& selection, unsigned short character)
{
    FrameSelection tempSelection;
    tempSelection.setSelection(selection);
    switch (character) {
    case KEYCODE_LEFT:
        tempSelection.modify(FrameSelection::AlterationExtend, DirectionLeft, CharacterGranularity);
        break;
    case KEYCODE_RIGHT:
        tempSelection.modify(FrameSelection::AlterationExtend, DirectionRight, CharacterGranularity);
        break;
    case KEYCODE_UP:
        tempSelection.modify(FrameSelection::AlterationExtend, DirectionBackward, LineGranularity);
        break;
    case KEYCODE_DOWN:
        tempSelection.modify(FrameSelection::AlterationExtend, DirectionForward, LineGranularity);
        break;
    default:
        break;
    }

    if ((character == KEYCODE_LEFT || character == KEYCODE_RIGHT)
        && (!inSameLine(selection.visibleStart(), tempSelection.selection().visibleStart())
           || !inSameLine(selection.visibleEnd(), tempSelection.selection().visibleEnd())))
        return false;

    return tempSelection.selection().selectionType() == VisibleSelection::RangeSelection;
}

static int clamp(const int min, const int value, const int max)
{
    return value < min ? min : std::min(value, max);
}

static VisiblePosition directionalVisiblePositionAtExtentOfBox(Frame* frame, const WebCore::IntRect& boundingBox, unsigned short direction, const WebCore::IntPoint& basePoint)
{
    ASSERT(frame);

    if (!frame)
        return VisiblePosition();

    switch (direction) {
    case KEYCODE_LEFT:
        // Extend x to start and clamp y to the edge of bounding box.
        return frame->visiblePositionForPoint(WebCore::IntPoint(boundingBox.x(), clamp(boundingBox.y(), basePoint.y(), boundingBox.maxY())));
    case KEYCODE_RIGHT:
        // Extend x to end and clamp y to the edge of bounding box.
        return frame->visiblePositionForPoint(WebCore::IntPoint(boundingBox.maxX(), clamp(boundingBox.y(), basePoint.y(), boundingBox.maxY())));
    case KEYCODE_UP:
        // Extend y to top and clamp x to the edge of bounding box.
        return frame->visiblePositionForPoint(WebCore::IntPoint(clamp(boundingBox.x(), basePoint.x(), boundingBox.maxX()), boundingBox.y()));
    case KEYCODE_DOWN:
        // Extend y to bottom and clamp x to the edge of bounding box.
        return frame->visiblePositionForPoint(WebCore::IntPoint(clamp(boundingBox.x(), basePoint.x(), boundingBox.maxX()), boundingBox.maxY()));
    default:
        break;
    }

    return frame->visiblePositionForPoint(WebCore::IntPoint(basePoint.x(), basePoint.y()));
}

static bool pointIsOutsideOfBoundingBoxInDirection(unsigned direction, const WebCore::IntPoint& selectionPoint, const WebCore::IntRect& boundingBox)
{
    if ((direction == KEYCODE_LEFT && selectionPoint.x() < boundingBox.x())
        || (direction == KEYCODE_UP && selectionPoint.y() < boundingBox.y())
        || (direction == KEYCODE_RIGHT && selectionPoint.x() > boundingBox.maxX())
        || (direction == KEYCODE_DOWN && selectionPoint.y() > boundingBox.maxY()))
        return true;

    return false;
}

unsigned short SelectionHandler::extendSelectionToFieldBoundary(bool isStartHandle, const WebCore::IntPoint& selectionPoint, VisibleSelection& newSelection)
{
    Frame* focusedFrame = m_webPage->focusedOrMainFrame();
    if (!focusedFrame->document()->focusedNode() || !focusedFrame->document()->focusedNode()->renderer())
        return 0;

    FrameSelection* controller = focusedFrame->selection();

    WebCore::IntRect caretRect = isStartHandle ? controller->selection().visibleStart().absoluteCaretBounds()
                                      : controller->selection().visibleEnd().absoluteCaretBounds();

    WebCore::IntRect nodeBoundingBox = focusedFrame->document()->focusedNode()->renderer()->absoluteBoundingBoxRect();
    nodeBoundingBox.inflate(-1);

    // Start handle is outside of the field. Treat it as the changed handle and move
    // relative to the start caret rect.
    unsigned short character = directionOfPointRelativeToRect(selectionPoint, caretRect, isStartHandle /* useTopPadding */, !isStartHandle /* useBottomPadding */);

    // Prevent incorrect movement, handles can only extend the selection this way
    // to prevent inversion of the handles.
    if (isStartHandle && (character == KEYCODE_RIGHT || character == KEYCODE_DOWN)
        || !isStartHandle && (character == KEYCODE_LEFT || character == KEYCODE_UP))
        character = 0;

    VisiblePosition newVisiblePosition = isStartHandle ? controller->selection().extent() : controller->selection().base();
    // Extend the selection to the bounds of the box before doing incremental scroll if the point is outside the node.
    // Don't extend selection and handle the character at the same time.
    if (pointIsOutsideOfBoundingBoxInDirection(character, selectionPoint, nodeBoundingBox))
        newVisiblePosition = directionalVisiblePositionAtExtentOfBox(focusedFrame, nodeBoundingBox, character, selectionPoint);

    if (isStartHandle)
        newSelection = VisibleSelection(newVisiblePosition, newSelection.extent(), true /* isDirectional */);
    else
        newSelection = VisibleSelection(newSelection.base(), newVisiblePosition, true /* isDirectional */);

    // If no selection will be changed, return the character to extend using navigation.
    if (controller->selection() == newSelection)
        return character;

    // Selection has been updated.
    return 0;
}

// Returns true if handled.
bool SelectionHandler::updateOrHandleInputSelection(VisibleSelection& newSelection, const WebCore::IntPoint& relativeStart
                                                    , const WebCore::IntPoint& relativeEnd)
{
    ASSERT(m_webPage->m_inputHandler->isInputMode());

    Frame* focusedFrame = m_webPage->focusedOrMainFrame();
    Node* focusedNode = focusedFrame->document()->focusedNode();
    if (!focusedNode || !focusedNode->renderer())
        return false;

    FrameSelection* controller = focusedFrame->selection();

    WebCore::IntRect currentStartCaretRect = controller->selection().visibleStart().absoluteCaretBounds();
    WebCore::IntRect currentEndCaretRect = controller->selection().visibleEnd().absoluteCaretBounds();

    // Check if the handle movement is valid.
    if (!shouldUpdateSelectionOrCaretForPoint(relativeStart, currentStartCaretRect, true /* startCaret */)
        || !shouldUpdateSelectionOrCaretForPoint(relativeEnd, currentEndCaretRect, false /* startCaret */)) {
        selectionPositionChanged(true /* forceUpdateWithoutChange */);
        return true;
    }

    WebCore::IntRect nodeBoundingBox = focusedNode->renderer()->absoluteBoundingBoxRect();

    // Only do special handling if one handle is outside of the node.
    bool startIsOutsideOfField = relativeStart != DOMSupport::InvalidPoint && !nodeBoundingBox.contains(relativeStart);
    bool endIsOutsideOfField = relativeEnd != DOMSupport::InvalidPoint && !nodeBoundingBox.contains(relativeEnd);
    if (startIsOutsideOfField && endIsOutsideOfField)
        return false;

    unsigned short character = 0;
    if (startIsOutsideOfField) {
        character = extendSelectionToFieldBoundary(true /* isStartHandle */, relativeStart, newSelection);
        if (character) {
            // Invert the selection so that the cursor point is at the beginning.
            controller->setSelection(VisibleSelection(controller->selection().end(), controller->selection().start(), true /* isDirectional */));
        }
    } else if (endIsOutsideOfField) {
        character = extendSelectionToFieldBoundary(false /* isStartHandle */, relativeEnd, newSelection);
        if (character) {
            // Reset the selection so that the end is the edit point.
            controller->setSelection(VisibleSelection(controller->selection().start(), controller->selection().end(), true /* isDirectional */));
        }
    }

    if (!character)
        return false;

    SelectionLog(LogLevelInfo, "SelectionHandler::updateOrHandleInputSelection making selection change attempt using key event %d", character);

    if (shouldExtendSelectionInDirection(controller->selection(), character))
        m_webPage->m_inputHandler->handleKeyboardInput(Platform::KeyboardEvent(character, Platform::KeyboardEvent::KeyDown, KEYMOD_SHIFT));

    // Send the selection changed in case this does not trigger a selection change to
    // ensure the caret position is accurate. This may be a duplicate event.
    selectionPositionChanged(true /* forceUpdateWithoutChange */);
    return true;
}

void SelectionHandler::setSelection(const WebCore::IntPoint& start, const WebCore::IntPoint& end)
{
    m_selectionActive = true;

    ASSERT(m_webPage);
    ASSERT(m_webPage->focusedOrMainFrame());
    ASSERT(m_webPage->focusedOrMainFrame()->selection());

    Frame* focusedFrame = m_webPage->focusedOrMainFrame();
    FrameSelection* controller = focusedFrame->selection();

#if SHOWDEBUG_SELECTIONHANDLER_TIMING
    m_timer.start();
#endif

    SelectionLog(LogLevelInfo, "SelectionHandler::setSelection adjusted points %d, %d, %d, %d", start.x(), start.y(), end.x(), end.y());

    // Note that IntPoint(-1, -1) is being our sentinel so far for
    // clipped out selection starting or ending location.
    bool startIsValid = start != DOMSupport::InvalidPoint;
    m_lastUpdatedEndPointIsValid = end != DOMSupport::InvalidPoint;

    // At least one of the locations must be valid.
    ASSERT(startIsValid || m_lastUpdatedEndPointIsValid);

    WebCore::IntPoint relativeStart = start;
    WebCore::IntPoint relativeEnd = end;

    VisibleSelection newSelection(controller->selection());

    // We need the selection to be ordered base then extent.
    if (!controller->selection().isBaseFirst())
        controller->setSelection(VisibleSelection(controller->selection().start(), controller->selection().end(), true /* isDirectional */));

    // We don't return early in the following, so that we can do input field scrolling if the
    // handle is outside the bounds of the field. This can be extended to handle sub-region
    // scrolling as well
    if (startIsValid) {
        relativeStart = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, start);

        VisiblePosition base = visiblePositionForPointIgnoringClipping(*focusedFrame, clipPointToVisibleContainer(start));
        if (base.isNotNull()) {
            // The function setBase validates the "base"
            newSelection.setBase(base);
            newSelection.setWithoutValidation(newSelection.base(), controller->selection().end());
            // Don't return early.
        }
    }

    if (m_lastUpdatedEndPointIsValid) {
        relativeEnd = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, end);

        VisiblePosition extent = visiblePositionForPointIgnoringClipping(*focusedFrame, clipPointToVisibleContainer(end));
        if (extent.isNotNull()) {
            // The function setExtent validates the "extent"
            newSelection.setExtent(extent);
            newSelection.setWithoutValidation(controller->selection().start(), newSelection.extent());
            // Don't return early.
        }
    }

    newSelection.setIsDirectional(true);

    if (m_webPage->m_inputHandler->isInputMode()) {
        if (updateOrHandleInputSelection(newSelection, relativeStart, relativeEnd))
            return;
    }

    if (controller->selection() == newSelection) {
        selectionPositionChanged(true /* forceUpdateWithoutChange */);
        return;
    }

    // If the selection size is reduce to less than a character, selection type becomes
    // Caret. As long as it is still a range, it's a valid selection. Selection cannot
    // be cancelled through this function.
    Vector<FloatQuad> quads;
    DOMSupport::visibleTextQuads(newSelection, quads);

    IntRectRegion unclippedRegion;
    regionForTextQuads(quads, unclippedRegion, false /* shouldClipToVisibleContent */);

    if (unclippedRegion.isEmpty()) {
        // Requested selection results in an empty selection, skip this change.
        selectionPositionChanged(true /* forceUpdateWithoutChange */);

        SelectionLog(LogLevelWarn, "SelectionHandler::setSelection selection points invalid, selection not updated.");
        return;
    }

    // Check if the handles reversed position.
    if (m_selectionActive && !newSelection.isBaseFirst())
        m_webPage->m_client->notifySelectionHandlesReversed();

    controller->setSelection(newSelection);
    SelectionLog(LogLevelInfo, "SelectionHandler::setSelection selection points valid, selection updated.");
}

// FIXME re-use this in context. Must be updated to include an option to return the href.
// This function should be moved to a new unit file. Names suggetions include DOMQueries
// and NodeTypes. Functions currently in InputHandler.cpp, SelectionHandler.cpp and WebPage.cpp
// can all be moved in.
static Node* enclosingLinkEventParentForNode(Node* node)
{
    if (!node)
        return 0;

    Node* linkNode = node->enclosingLinkEventParentOrSelf();
    return linkNode && linkNode->isLink() ? linkNode : 0;
}

void SelectionHandler::selectAtPoint(const WebCore::IntPoint& location)
{
    // If point is invalid trigger selection based expansion.
    if (location == DOMSupport::InvalidPoint) {
        selectObject(WordGranularity);
        return;
    }

    Node* targetNode;
    WebCore::IntPoint targetPosition;
    // FIXME: Factory this get right fat finger code into a helper.
    const FatFingersResult lastFatFingersResult = m_webPage->m_touchEventHandler->lastFatFingersResult();
    if (lastFatFingersResult.resultMatches(location, FatFingers::Text) && lastFatFingersResult.positionWasAdjusted() && lastFatFingersResult.nodeAsElementIfApplicable()) {
        targetNode = lastFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed);
        targetPosition = lastFatFingersResult.adjustedPosition();
    } else {
        FatFingersResult newFatFingersResult = FatFingers(m_webPage, location, FatFingers::Text).findBestPoint();
        if (!newFatFingersResult.positionWasAdjusted())
            return;

        targetPosition = newFatFingersResult.adjustedPosition();
        targetNode = newFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed);
    }

    ASSERT(targetNode);

    // If the node at the point is a link, focus on the entire link, not a word.
    if (Node* link = enclosingLinkEventParentForNode(targetNode)) {
        selectObject(link);
        return;
    }

    // selectAtPoint API currently only supports WordGranularity but may be extended in the future.
    selectObject(targetPosition, WordGranularity);
}

static bool expandSelectionToGranularity(Frame* frame, VisibleSelection selection, TextGranularity granularity, bool isInputMode)
{
    ASSERT(frame);
    ASSERT(frame->selection());

    if (!(selection.start().anchorNode() && selection.start().anchorNode()->isTextNode()))
        return false;

    if (granularity == WordGranularity)
        selection = DOMSupport::visibleSelectionForClosestActualWordStart(selection);

    selection.expandUsingGranularity(granularity);
    selection.setAffinity(frame->selection()->affinity());

    if (isInputMode && !frame->selection()->shouldChangeSelection(selection))
        return false;

    frame->selection()->setSelection(selection);
    return true;
}

void SelectionHandler::selectObject(const WebCore::IntPoint& location, TextGranularity granularity)
{
    ASSERT(location.x() >= 0 && location.y() >= 0);
    ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection());
    Frame* focusedFrame = m_webPage->focusedOrMainFrame();

    SelectionLog(LogLevelInfo, "SelectionHandler::selectObject adjusted points %d, %d", location.x(), location.y());

    WebCore::IntPoint relativePoint = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, location);
    VisiblePosition pointLocation(focusedFrame->visiblePositionForPoint(relativePoint));
    VisibleSelection selection = VisibleSelection(pointLocation, pointLocation);

    m_selectionActive = expandSelectionToGranularity(focusedFrame, selection, granularity, m_webPage->m_inputHandler->isInputMode());
}

void SelectionHandler::selectObject(TextGranularity granularity)
{
    ASSERT(m_webPage && m_webPage->m_inputHandler);
    // Using caret location, must be inside an input field.
    if (!m_webPage->m_inputHandler->isInputMode())
        return;

    ASSERT(m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection());
    Frame* focusedFrame = m_webPage->focusedOrMainFrame();

    SelectionLog(LogLevelInfo, "SelectionHandler::selectObject using current selection");

    // Use the current selection as the selection point.
    ASSERT(focusedFrame->selection()->selectionType() != VisibleSelection::NoSelection);
    m_selectionActive = expandSelectionToGranularity(focusedFrame, focusedFrame->selection()->selection(), granularity, true /* isInputMode */);
}

void SelectionHandler::selectObject(Node* node)
{
    if (!node)
        return;

    m_selectionActive = true;

    ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection());
    Frame* focusedFrame = m_webPage->focusedOrMainFrame();

    SelectionLog(LogLevelInfo, "SelectionHandler::selectNode");

    VisibleSelection selection = VisibleSelection::selectionFromContentsOfNode(node);
    focusedFrame->selection()->setSelection(selection);
}

static TextDirection directionOfEnclosingBlock(FrameSelection* selection)
{
    Node* enclosingBlockNode = enclosingBlock(selection->selection().extent().deprecatedNode());
    if (!enclosingBlockNode)
        return LTR;

    if (RenderObject* renderer = enclosingBlockNode->renderer())
        return renderer->style()->direction();

    return LTR;
}

// Returns > 0 if p1 is "closer" to referencePoint, < 0 if p2 is "closer", 0 if they are equidistant.
// Because text is usually arranged in horizontal rows, distance is measured along the y-axis, with x-axis used only to break ties.
// If rightGravity is true, the right-most x-coordinate is chosen, otherwise teh left-most coordinate is chosen.
static inline int comparePointsToReferencePoint(const WebCore::IntPoint& p1, const WebCore::IntPoint& p2, const WebCore::IntPoint& referencePoint, bool rightGravity)
{
    int dy1 = abs(referencePoint.y() - p1.y());
    int dy2 = abs(referencePoint.y() - p2.y());
    if (dy1 != dy2)
        return dy2 - dy1;

    // Same y-coordinate, choose the farthest right (or left) point.
    if (p1.x() == p2.x())
        return 0;

    if (p1.x() > p2.x())
        return rightGravity ? 1 : -1;

    return rightGravity ? -1 : 1;
}

// NOTE/FIXME: Due to r77286, we are getting off-by-one results in the IntRect class counterpart implementation of the
//             methods below. As done in r89803, r77928 and a few others, lets use local method to fix it.
//             We should keep our eyes very open on it, since it can affect BackingStore very badly.
static WebCore::IntPoint minXMinYCorner(const WebCore::IntRect& rect) { return rect.location(); } // typically topLeft
static WebCore::IntPoint maxXMinYCorner(const WebCore::IntRect& rect) { return WebCore::IntPoint(rect.x() + rect.width() - 1, rect.y()); } // typically topRight
static WebCore::IntPoint minXMaxYCorner(const WebCore::IntRect& rect) { return WebCore::IntPoint(rect.x(), rect.y() + rect.height() - 1); } // typically bottomLeft
static WebCore::IntPoint maxXMaxYCorner(const WebCore::IntRect& rect) { return WebCore::IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height() - 1); } // typically bottomRight

// The caret is a one-pixel wide line down either the right or left edge of a
// rect, depending on the text direction.
static inline bool caretIsOnLeft(bool isStartCaret, bool isRTL)
{
    if (isStartCaret)
        return !isRTL;

    return isRTL;
}

static inline WebCore::IntPoint caretLocationForRect(const WebCore::IntRect& rect, bool isStartCaret, bool isRTL)
{
    return caretIsOnLeft(isStartCaret, isRTL) ? minXMinYCorner(rect) : maxXMinYCorner(rect);
}

static inline WebCore::IntPoint caretComparisonPointForRect(const WebCore::IntRect& rect, bool isStartCaret, bool isRTL)
{
    if (isStartCaret)
        return caretIsOnLeft(isStartCaret, isRTL) ? minXMinYCorner(rect) : maxXMinYCorner(rect);

    return caretIsOnLeft(isStartCaret, isRTL) ? minXMaxYCorner(rect) : maxXMaxYCorner(rect);
}

static void adjustCaretRects(WebCore::IntRect& startCaret, bool isStartCaretClippedOut,
                             WebCore::IntRect& endCaret, bool isEndCaretClippedOut,
                             const std::vector<Platform::IntRect> rectList,
                             const WebCore::IntPoint& startReferencePoint,
                             const WebCore::IntPoint& endReferencePoint,
                             bool isRTL)
{
    // startReferencePoint is the best guess at the top left of the selection; endReferencePoint is the best guess at the bottom right.
    if (isStartCaretClippedOut)
        startCaret.setLocation(DOMSupport::InvalidPoint);
    else {
        startCaret = rectList[0];
        startCaret.setLocation(caretLocationForRect(startCaret, true, isRTL));
        // Reset width to 1 as we are strictly interested in caret location.
        startCaret.setWidth(1);
    }

    if (isEndCaretClippedOut)
        endCaret.setLocation(DOMSupport::InvalidPoint);
    else {
        endCaret = rectList[0];
        endCaret.setLocation(caretLocationForRect(endCaret, false, isRTL));
        // Reset width to 1 as we are strictly interested in caret location.
        endCaret.setWidth(1);
    }

    if (isStartCaretClippedOut && isEndCaretClippedOut)
        return;

    for (unsigned i = 1; i < rectList.size(); i++) {
        WebCore::IntRect currentRect(rectList[i]);

        // Compare and update the start and end carets with their respective reference points.
        if (!isStartCaretClippedOut && comparePointsToReferencePoint(
                    caretComparisonPointForRect(currentRect, true, isRTL),
                    caretComparisonPointForRect(startCaret, true, isRTL),
                    startReferencePoint, isRTL) > 0) {
            startCaret.setLocation(caretLocationForRect(currentRect, true, isRTL));
            startCaret.setHeight(currentRect.height());
        }

        if (!isEndCaretClippedOut && comparePointsToReferencePoint(
                    caretComparisonPointForRect(currentRect, false, isRTL),
                    caretComparisonPointForRect(endCaret, false, isRTL),
                    endReferencePoint, !isRTL) > 0) {
            endCaret.setLocation(caretLocationForRect(currentRect, false, isRTL));
            endCaret.setHeight(currentRect.height());
        }
    }
}

WebCore::IntPoint SelectionHandler::clipPointToVisibleContainer(const WebCore::IntPoint& point) const
{
    ASSERT(m_webPage->m_mainFrame && m_webPage->m_mainFrame->view());

    Frame* frame = m_webPage->focusedOrMainFrame();
    WebCore::IntPoint clippedPoint = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), frame, point, true /* clampToTargetFrame */);

    if (m_webPage->m_inputHandler->isInputMode()
            && frame->document()->focusedNode()
            && frame->document()->focusedNode()->renderer()) {
        WebCore::IntRect boundingBox(frame->document()->focusedNode()->renderer()->absoluteBoundingBoxRect());
        boundingBox.inflate(-1);
        clippedPoint = WebCore::IntPoint(clamp(boundingBox.x(), clippedPoint.x(), boundingBox.maxX()), clamp(boundingBox.y(), clippedPoint.y(), boundingBox.maxY()));
    }

    return clippedPoint;
}

static WebCore::IntPoint referencePoint(const VisiblePosition& position, const WebCore::IntRect& boundingRect, const WebCore::IntPoint& framePosition, bool isStartCaret, bool isRTL)
{
    // If one of the carets is invalid (this happens, for instance, if the
    // selection ends in an empty div) fall back to using the corner of the
    // entire region (which is already in frame coordinates so doesn't need
    // adjusting).
    WebCore::IntRect startCaretBounds(position.absoluteCaretBounds());
    if (startCaretBounds.isEmpty())
        startCaretBounds = boundingRect;
    else
        startCaretBounds.move(framePosition.x(), framePosition.y());

    return caretComparisonPointForRect(startCaretBounds, isStartCaret, isRTL);
}

// Check all rects in the region for a point match. The region is non-banded
// and non-sorted so all must be checked.
static bool regionRectListContainsPoint(const IntRectRegion& region, const WebCore::IntPoint& point)
{
    if (!region.extents().contains(point))
        return false;

    std::vector<Platform::IntRect> rectList = region.rects();
    for (unsigned int i = 0; i < rectList.size(); i++) {
        if (rectList[i].contains(point))
            return true;
    }
    return false;
}

bool SelectionHandler::inputNodeOverridesTouch() const
{
    if (!m_webPage->m_inputHandler->isInputMode())
        return false;

    Node* focusedNode = m_webPage->focusedOrMainFrame()->document()->focusedNode();
    if (!focusedNode || !focusedNode->isElementNode())
        return false;

    // TODO consider caching this in InputHandler so it is only calculated once per focus.
    DEFINE_STATIC_LOCAL(QualifiedName, selectionTouchOverrideAttr, (nullAtom, "data-blackberry-end-selection-on-touch", nullAtom));
    Element* element = static_cast<Element*>(focusedNode);
    return DOMSupport::elementAttributeState(element, selectionTouchOverrideAttr) == DOMSupport::On;
}

// Note: This is the only function in SelectionHandler in which the coordinate
// system is not entirely WebKit.
void SelectionHandler::selectionPositionChanged(bool forceUpdateWithoutChange)
{
    SelectionLog(LogLevelInfo, "SelectionHandler::selectionPositionChanged forceUpdateWithoutChange = %s", forceUpdateWithoutChange ? "true" : "false");

    // This method can get called during WebPage shutdown process.
    // If that is the case, just bail out since the client is not
    // in a safe state of trust to request anything else from it.
    if (!m_webPage->m_mainFrame)
        return;

    if (m_webPage->m_inputHandler->isInputMode() && m_webPage->m_inputHandler->processingChange()) {
        m_webPage->m_client->cancelSelectionVisuals();

        // Since we're not calling notifyCaretPositionChangedIfNeeded now, we have to do so at the end of processing
        // to avoid dropping a notification.
        m_didSuppressCaretPositionChangedNotification = true;
        return;
    }

    notifyCaretPositionChangedIfNeeded();

    // Enter selection mode if selection type is RangeSelection, and disable selection if
    // selection is active and becomes caret selection.
    Frame* frame = m_webPage->focusedOrMainFrame();
    WebCore::IntPoint framePos = m_webPage->frameOffset(frame);
    if (m_selectionActive && (m_caretActive || frame->selection()->isNone()))
        m_selectionActive = false;
    else if (frame->selection()->isRange())
        m_selectionActive = true;
    else if (!m_selectionActive)
        return;

    SelectionTimingLog(LogLevelInfo, "SelectionHandler::selectionPositionChanged starting at %f", m_timer.elapsed());

    WebCore::IntRect startCaret(DOMSupport::InvalidPoint, WebCore::IntSize());
    WebCore::IntRect endCaret(DOMSupport::InvalidPoint, WebCore::IntSize());

    // Get the text rects from the selections range.
    Vector<FloatQuad> quads;
    DOMSupport::visibleTextQuads(frame->selection()->selection(), quads);

    IntRectRegion unclippedRegion;
    regionForTextQuads(quads, unclippedRegion, false /* shouldClipToVisibleContent */);

    // If there is no change in selected text and the visual rects
    // have not changed then don't bother notifying anything.
    if (!forceUpdateWithoutChange && m_lastSelectionRegion.isEqual(unclippedRegion))
        return;

    m_lastSelectionRegion = unclippedRegion;

    IntRectRegion visibleSelectionRegion;
    if (!unclippedRegion.isEmpty()) {
        WebCore::IntRect unclippedStartCaret;
        WebCore::IntRect unclippedEndCaret;

        bool isRTL = directionOfEnclosingBlock(frame->selection()) == RTL;

        WebCore::IntPoint startCaretReferencePoint = referencePoint(frame->selection()->selection().visibleStart(), unclippedRegion.extents(), framePos, true /* isStartCaret */, isRTL);
        WebCore::IntPoint endCaretReferencePoint = referencePoint(frame->selection()->selection().visibleEnd(), unclippedRegion.extents(), framePos, false /* isStartCaret */, isRTL);

        adjustCaretRects(unclippedStartCaret, false /* unclipped */, unclippedEndCaret, false /* unclipped */, unclippedRegion.rects(), startCaretReferencePoint, endCaretReferencePoint, isRTL);

        regionForTextQuads(quads, visibleSelectionRegion);

#if SHOWDEBUG_SELECTIONHANDLER // Don't rely just on SelectionLog to avoid loop.
        for (unsigned int i = 0; i < unclippedRegion.numRects(); i++)
            SelectionLog(LogLevelInfo, "Rect list - Unmodified #%d, (%d, %d) (%d x %d)", i, unclippedRegion.rects()[i].x(), unclippedRegion.rects()[i].y(), unclippedRegion.rects()[i].width(), unclippedRegion.rects()[i].height());
        for (unsigned int i = 0; i < visibleSelectionRegion.numRects(); i++)
            SelectionLog(LogLevelInfo, "Rect list  - Clipped to Visible #%d, (%d, %d) (%d x %d)", i, visibleSelectionRegion.rects()[i].x(), visibleSelectionRegion.rects()[i].y(), visibleSelectionRegion.rects()[i].width(), visibleSelectionRegion.rects()[i].height());
#endif

        bool shouldCareAboutPossibleClippedOutSelection = frame != m_webPage->mainFrame() || m_webPage->m_inputHandler->isInputMode();

        if (!visibleSelectionRegion.isEmpty() || shouldCareAboutPossibleClippedOutSelection) {
            // Adjust the handle markers to be at the end of the painted rect. When selecting links
            // and other elements that may have a larger visible area than needs to be rendered a gap
            // can exist between the handle and overlay region.

            bool shouldClipStartCaret = !regionRectListContainsPoint(visibleSelectionRegion, unclippedStartCaret.location());
            bool shouldClipEndCaret = !regionRectListContainsPoint(visibleSelectionRegion, unclippedEndCaret.location());

            // Find the top corner and bottom corner.
            adjustCaretRects(startCaret, shouldClipStartCaret, endCaret, shouldClipEndCaret, visibleSelectionRegion.rects(), startCaretReferencePoint, endCaretReferencePoint, isRTL);

            // Translate the caret values as they must be in transformed coordinates.
            if (!shouldClipStartCaret) {
                startCaret = m_webPage->mapToTransformed(startCaret);
                m_webPage->clipToTransformedContentsRect(startCaret);
            }

            if (!shouldClipEndCaret) {
                endCaret = m_webPage->mapToTransformed(endCaret);
                m_webPage->clipToTransformedContentsRect(endCaret);
            }
        }
    }

    SelectionLog(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::selectionPositionChanged Start Rect=(%d, %d) (%d x %d) End Rect=(%d, %d) (%d x %d)",
                    startCaret.x(), startCaret.y(), startCaret.width(), startCaret.height(), endCaret.x(), endCaret.y(), endCaret.width(), endCaret.height());

    if (m_webPage->m_selectionOverlay)
        m_webPage->m_selectionOverlay->draw(visibleSelectionRegion);

    m_webPage->m_client->notifySelectionDetailsChanged(startCaret, endCaret, visibleSelectionRegion, inputNodeOverridesTouch());
    SelectionTimingLog(LogLevelInfo, "SelectionHandler::selectionPositionChanged completed at %f", m_timer.elapsed());
}


void SelectionHandler::notifyCaretPositionChangedIfNeeded()
{
    m_didSuppressCaretPositionChangedNotification = false;

    if (m_caretActive || (m_webPage->m_inputHandler->isInputMode() && m_webPage->focusedOrMainFrame()->selection()->isCaret())) {
        // This may update the caret to no longer be active.
        caretPositionChanged();
    }
}

// NOTE: This function is not in WebKit coordinates.
void SelectionHandler::caretPositionChanged()
{
    SelectionLog(LogLevelInfo, "SelectionHandler::caretPositionChanged");

    WebCore::IntRect caretLocation;
    // If the input field is empty, we always turn off the caret.
    // If the input field is not active, we must be turning off the caret.
    bool emptyInputField = m_webPage->m_inputHandler->elementText().isEmpty();
    if (emptyInputField || (!m_webPage->m_inputHandler->isInputMode() && m_caretActive)) {
        if (!emptyInputField)
            m_caretActive = false;
        // Send an empty caret change to turn off the caret.
        m_webPage->m_client->notifyCaretChanged(caretLocation, m_webPage->m_touchEventHandler->lastFatFingersResult().isTextInput() /* userTouchTriggered */);
        return;
    }

    ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection());

    // This function should only reach this point if input mode is active.
    ASSERT(m_webPage->m_inputHandler->isInputMode());

    WebCore::IntPoint frameOffset(m_webPage->frameOffset(m_webPage->focusedOrMainFrame()));
    WebCore::IntRect clippingRectForContent(clippingRectForVisibleContent());
    if (m_webPage->focusedOrMainFrame()->selection()->selectionType() == VisibleSelection::CaretSelection) {
        caretLocation = m_webPage->focusedOrMainFrame()->selection()->selection().visibleStart().absoluteCaretBounds();
        caretLocation.move(frameOffset.x(), frameOffset.y());

        // Clip against the containing frame and node boundaries.
        caretLocation.intersect(clippingRectForContent);
    }

    m_caretActive = !caretLocation.isEmpty();

    SelectionLog(LogLevelInfo, "SelectionHandler::caretPositionChanged caret Rect %d, %d, %dx%d",
                        caretLocation.x(), caretLocation.y(), caretLocation.width(), caretLocation.height());

    caretLocation = m_webPage->mapToTransformed(caretLocation);
    m_webPage->clipToTransformedContentsRect(caretLocation);

    bool singleLineInput = !m_webPage->m_inputHandler->isMultilineInputMode();
    WebCore::IntRect nodeBoundingBox = singleLineInput ? m_webPage->m_inputHandler->boundingBoxForInputField() : WebCore::IntRect();

    if (!nodeBoundingBox.isEmpty()) {
        nodeBoundingBox.move(frameOffset.x(), frameOffset.y());

        // Clip against the containing frame and node boundaries.
        nodeBoundingBox.intersect(clippingRectForContent);

        nodeBoundingBox = m_webPage->mapToTransformed(nodeBoundingBox);
        m_webPage->clipToTransformedContentsRect(nodeBoundingBox);
    }

    SelectionLog(LogLevelInfo, "SelectionHandler::single line %s single line bounding box %d, %d, %dx%d",
                    singleLineInput ? "true" : "false", nodeBoundingBox.x(), nodeBoundingBox.y(), nodeBoundingBox.width(), nodeBoundingBox.height());

    m_webPage->m_client->notifyCaretChanged(caretLocation, m_webPage->m_touchEventHandler->lastFatFingersResult().isTextInput() /* userTouchTriggered */, singleLineInput, nodeBoundingBox);
}

bool SelectionHandler::selectionContains(const WebCore::IntPoint& point)
{
    ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection());
    return m_webPage->focusedOrMainFrame()->selection()->contains(point);
}

}
}
