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

#if PLATFORM(IOS_FAMILY)

#import "WebFrameIOS.h"

#import <WebCore/DocumentMarkerController.h>
#import <WebCore/Editing.h>
#import <WebCore/Editor.h>
#import <WebCore/Element.h>
#import <WebCore/EventHandler.h>
#import <WebCore/FloatRect.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameSelection.h>
#import <WebCore/FrameSnapshotting.h>
#import <WebCore/FrameView.h>
#import <WebCore/HitTestResult.h>
#import <WebCore/Position.h>
#import <WebCore/Range.h>
#import <WebCore/RenderObject.h>
#import <WebCore/RenderText.h>
#import <WebCore/RenderedDocumentMarker.h>
#import <WebCore/SelectionRect.h>
#import <WebCore/TextBoundaries.h>
#import <WebCore/TextFlags.h>
#import <WebCore/VisiblePosition.h>
#import <WebCore/VisibleUnits.h>
#import <WebKitLegacy/DOM.h>
#import <WebKitLegacy/DOMRange.h>
#import <WebKitLegacy/DOMUIKitExtensions.h>
#import <WebKitLegacy/WebSelectionRect.h>
#import <WebKitLegacy/WebVisiblePosition.h>
#import <unicode/uchar.h>

#import "DOMNodeInternal.h"
#import "DOMRangeInternal.h"
#import "WebFrameInternal.h"
#import "WebUIKitDelegate.h"
#import "WebViewPrivate.h"
#import "WebVisiblePosition.h"
#import "WebVisiblePositionInternal.h"

using namespace WebCore;

//-------------------

@interface WebFrame (WebSecretsIKnowAbout)
- (VisiblePosition)_visiblePositionForPoint:(CGPoint)point;
@end

@implementation WebFrame (WebFrameIOS)

//-------------------

- (WebCore::Frame *)coreFrame
{
    return _private->coreFrame;
}

- (VisiblePosition)visiblePositionForPoint:(CGPoint)point
{
    return [self _visiblePositionForPoint:point];
}

- (VisiblePosition)closestWordBoundary:(VisiblePosition)position
{
    VisiblePosition start = startOfWord(position);
    VisiblePosition end = endOfWord(position);
    int startDistance = position.deepEquivalent().deprecatedEditingOffset() - start.deepEquivalent().deprecatedEditingOffset();
    int endDistance = end.deepEquivalent().deprecatedEditingOffset() - position.deepEquivalent().deprecatedEditingOffset() ;
    return (startDistance < endDistance) ? start : end;    
}

//-------------------

- (void)clearSelection
{
    Frame *frame = [self coreFrame];
    if (frame)
        frame->selection().clearCurrentSelection();
    
}

- (WebTextSelectionState)selectionState
{
    WebTextSelectionState state = WebTextSelectionStateNone;

    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();

    if (frameSelection.isCaret())
        state = WebTextSelectionStateCaret;
    else if (frameSelection.isRange())
        state = WebTextSelectionStateRange;

    return state;
}

- (BOOL)hasSelection
{
    WebTextSelectionState state = [self selectionState];
    return state == WebTextSelectionStateCaret || state == WebTextSelectionStateRange;
}

- (CGRect)caretRectForPosition:(WebVisiblePosition *)position
{
    return position ? [position _visiblePosition].absoluteCaretBounds() : CGRectZero;
}

- (CGRect)closestCaretRectInMarkedTextRangeForPoint:(CGPoint)point
{
    Frame *frame = [self coreFrame];
    Range *markedTextRange = frame->editor().compositionRange().get();
    VisibleSelection markedTextRangeSelection = markedTextRange ? VisibleSelection(*markedTextRange) : VisibleSelection();

    IntRect result;

    if (markedTextRangeSelection.isRange()) {
        VisiblePosition start(markedTextRangeSelection.start());
        VisiblePosition end(markedTextRangeSelection.end());

        // Adjust pos and give it an appropriate affinity.
        VisiblePosition pos;
        Vector<IntRect> intRects;
        markedTextRange->absoluteTextRects(intRects, NO);
        unsigned size = intRects.size();
        CGRect firstRect = intRects[0];
        CGRect lastRect  = intRects[size-1];
        if (point.y < firstRect.origin.y) {
            point.y = firstRect.origin.y;
            pos = [self visiblePositionForPoint:point];
            pos.setAffinity(UPSTREAM);
        }
        else if (point.y >= lastRect.origin.y) {
            point.y = lastRect.origin.y;
            pos = [self visiblePositionForPoint:point];
            pos.setAffinity(DOWNSTREAM);
        }
        else {
            pos = [self visiblePositionForPoint:point];
        }
        
        if (pos == start || pos < start) {
            start.setAffinity(UPSTREAM);
            result = start.absoluteCaretBounds();
        } else if (pos > end) {
            end.setAffinity(DOWNSTREAM);
            result = end.absoluteCaretBounds();
        } else {
            result = pos.absoluteCaretBounds();
        }
    } else {
        VisiblePosition pos = [self visiblePositionForPoint:point];
        result = pos.absoluteCaretBounds();
    }
    
    return (CGRect) result;    
}


- (void)collapseSelection
{
    if ([self selectionState] == WebTextSelectionStateRange) {
        Frame *frame = [self coreFrame];
        FrameSelection& frameSelection = frame->selection();
        VisiblePosition end(frameSelection.selection().end());
        frameSelection.moveTo(end);
    }
}

- (void)extendSelection:(BOOL)start
{
    if ([self selectionState] == WebTextSelectionStateRange) {
        Frame *frame = [self coreFrame];
        const VisibleSelection& originalSelection = frame->selection().selection();
        if (start) {
            VisiblePosition start = startOfWord(originalSelection.start());
            frame->selection().moveTo(start, originalSelection.end());
        } else {
            VisiblePosition end = endOfWord(originalSelection.end());
            frame->selection().moveTo(originalSelection.start(), end);
        }
    }    
}

- (NSArray *)selectionRectsForCoreRange:(Range *)range
{
    if (!range)
        return nil;
    
    Vector<SelectionRect> rects;
    range->collectSelectionRects(rects);
    unsigned size = rects.size();
    
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:size];
    for (unsigned i = 0; i < size; i++) {
        SelectionRect &coreRect = rects[i];
        WebSelectionRect *webRect = [WebSelectionRect selectionRect];
        webRect.rect = static_cast<CGRect>(coreRect.rect());
        webRect.writingDirection = coreRect.direction() == TextDirection::LTR ? WKWritingDirectionLeftToRight : WKWritingDirectionRightToLeft;
        webRect.isLineBreak = coreRect.isLineBreak();
        webRect.isFirstOnLine = coreRect.isFirstOnLine();
        webRect.isLastOnLine = coreRect.isLastOnLine();
        webRect.containsStart = coreRect.containsStart();
        webRect.containsEnd = coreRect.containsEnd();
        webRect.isInFixedPosition = coreRect.isInFixedPosition();
        webRect.isHorizontal = coreRect.isHorizontal();
        [result addObject:webRect];
    }
    
    return result;        
}

- (NSArray *)selectionRectsForRange:(DOMRange *)domRange
{
    return [self selectionRectsForCoreRange:core(domRange)];
}

- (NSArray *)selectionRects
{
    if (![self hasSelection])
        return nil;

    Frame *frame = [self coreFrame];
    return [self selectionRectsForCoreRange:frame->selection().toNormalizedRange().get()];
}

- (DOMRange *)wordAtPoint:(CGPoint)point
{
    VisiblePosition pos = [self visiblePositionForPoint:point];
    VisiblePosition start = startOfWord(pos);
    VisiblePosition end = endOfWord(pos);
    DOMRange *wordRange = kit(makeRange(start, end).get());
    return wordRange;   
}

- (WebVisiblePosition *)webVisiblePositionForPoint:(CGPoint)point
{
    return [WebVisiblePosition _wrapVisiblePosition:[self visiblePositionForPoint:point]];
}

- (void)setRangedSelectionBaseToCurrentSelection
{
    Frame *frame = [self coreFrame];
    frame->setRangedSelectionBaseToCurrentSelection();
}

- (void)setRangedSelectionBaseToCurrentSelectionStart
{
    Frame *frame = [self coreFrame];
    frame->setRangedSelectionBaseToCurrentSelectionStart();
}

- (void)setRangedSelectionBaseToCurrentSelectionEnd
{
    Frame *frame = [self coreFrame];
    frame->setRangedSelectionBaseToCurrentSelectionEnd();
}

- (void)clearRangedSelectionInitialExtent
{
    Frame *frame = [self coreFrame];
    frame->clearRangedSelectionInitialExtent();
}

- (void)setRangedSelectionInitialExtentToCurrentSelectionStart
{
    Frame *frame = [self coreFrame];
    frame->setRangedSelectionInitialExtentToCurrentSelectionStart();
}

- (void)setRangedSelectionInitialExtentToCurrentSelectionEnd
{
    Frame *frame = [self coreFrame];
    frame->setRangedSelectionInitialExtentToCurrentSelectionEnd();
}

- (void)setRangedSelectionWithExtentPoint:(CGPoint)point
{    
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    VisiblePosition pos = [self visiblePositionForPoint:point];
    VisibleSelection base = frame->rangedSelectionBase();
    
    if (pos.isNull() || !base.isRange())
        return;
    
    VisiblePosition start(base.start());
    VisiblePosition end(base.end());    
    
    if (pos < start) {        
        frameSelection.moveTo(pos, end);
    } 
    else if (pos > end) {
        frameSelection.moveTo(start, pos);
    } 
    else {
        frameSelection.moveTo(start, end);
    }
}

- (BOOL)setRangedSelectionExtentPoint:(CGPoint)extentPoint baseIsStart:(BOOL)baseIsStart allowFlipping:(BOOL)allowFlipping
{
    Frame *frame = [self coreFrame];
    VisibleSelection rangedSelectionBase(frame->rangedSelectionBase());
    VisiblePosition baseStart(rangedSelectionBase.start(), rangedSelectionBase.affinity());
    VisiblePosition baseEnd;
    if (rangedSelectionBase.isNone()) {
        return baseIsStart;
    }
    else if (rangedSelectionBase.isCaret()) {
        baseEnd = baseStart;
    }
    else {
        baseEnd = VisiblePosition(rangedSelectionBase.end(), rangedSelectionBase.affinity());
    }

    VisiblePosition extent([self visiblePositionForPoint:extentPoint]);
    
    if (rangedSelectionBase.isRange() && baseStart < extent && extent < baseEnd) {
        frame->selection().moveTo(baseStart, baseEnd);
        return NO;
    }    
    
    CGRect caretRect = baseIsStart ? baseStart.absoluteCaretBounds() : baseEnd.absoluteCaretBounds();
    CGPoint basePoint = CGPointMake(caretRect.origin.x, caretRect.origin.y);

    static const CGFloat FlipMargin = 30;
    bool didFlipStartEnd = false;
    bool canFlipStartEnd = allowFlipping && 
        (fabs(basePoint.x - extentPoint.x) > FlipMargin || fabs(basePoint.y - extentPoint.y) > FlipMargin);

    VisiblePosition base;
    if (baseIsStart) {                
        base = baseStart;
        BOOL wouldFlip = (extent < base);
        if (wouldFlip) {
            if (!canFlipStartEnd) {
                // We're going to prevent flipping.  First try for a position on the same line.
                // If that fails, just choose something after the start.
                CGRect baseCaret = base.absoluteCaretBounds();
                bool baseIsHorizontal = baseCaret.size.height > baseCaret.size.width;
                CGPoint pointInLine = baseIsHorizontal ? CGPointMake(extentPoint.x, CGRectGetMidY(baseCaret)) :
                                                         CGPointMake(CGRectGetMidX(baseCaret), extentPoint.y);
                VisiblePosition positionInLine = [self visiblePositionForPoint:pointInLine];
                if (positionInLine.isNotNull() && positionInLine > base) {
                    extent = positionInLine;
                } else {
                    extent = base.next();
                }
            } else {
                didFlipStartEnd = YES;
            }
        }
        
        if (base == extent)
            extent = base.next();
    }
    else {
        base = baseEnd;
        BOOL wouldFlip = (extent > base);
        if (wouldFlip) {
            if (!canFlipStartEnd) {
                // We're going to prevent flipping.  First try for a position on the same line.
                // If that fails, just choose something before the end.
                CGRect baseCaret = base.absoluteCaretBounds();
                bool baseIsHorizontal = baseCaret.size.height > baseCaret.size.width;
                CGPoint pointInLine = baseIsHorizontal ? CGPointMake(extentPoint.x, CGRectGetMidY(baseCaret)) :
                                                         CGPointMake(CGRectGetMidX(baseCaret), extentPoint.y);
                VisiblePosition positionInLine = [self visiblePositionForPoint:pointInLine];
                if (positionInLine.isNotNull() && positionInLine < base) {
                    extent = positionInLine;
                } else {
                    extent = base.previous();
                }
            } else {
                didFlipStartEnd = YES;
            }
        }
        
        if (base == extent)
            extent = base.previous();
    }
    
    frame->selection().moveTo(base, extent);

    return didFlipStartEnd ? !baseIsStart : baseIsStart;
}

- (BOOL)setSelectionWithBasePoint:(CGPoint)basePoint extentPoint:(CGPoint)extentPoint baseIsStart:(BOOL)baseIsStart allowFlipping:(BOOL)allowFlipping
{
    // This function updates the selection using two points and an existing notion of
    // which is the base and which is the extent. However, if the allowFlipping argument
    // is YES, it will allow the base and extent positions to flip if the extent moves a
    // certain amount to the "other side" of the base. When a flip of start/end occurs
    // relative to base/extent,  this is reported back to the calling code, which is then
    // expected to take the flip into account in subsequent calls to this function (for at
    // least as long as a single, logical selection session continues).

    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    VisiblePosition base([self visiblePositionForPoint:basePoint]);
    VisiblePosition extent([self visiblePositionForPoint:extentPoint]);

    static const CGFloat FlipMargin = 30;
    bool didFlipStartEnd = false;
    bool canFlipStartEnd = allowFlipping &&
                        ((baseIsStart &&  (extentPoint.x <= basePoint.x - FlipMargin || extentPoint.y <= basePoint.y - FlipMargin)) ||
                         (!baseIsStart && (extentPoint.x >= basePoint.x + FlipMargin || extentPoint.y >= basePoint.y + FlipMargin)));
    
                        
    if (extent == base) {
        extent = baseIsStart ? base.next() : base.previous();
    }
    else if (baseIsStart && extent < base) {
        if (canFlipStartEnd)
            didFlipStartEnd = true;
        else
            extent = base.next();
    }
    else if (!baseIsStart && extent > base) {
        if (canFlipStartEnd)
            didFlipStartEnd = true;
        else
            extent = base.previous();
    }

    frameSelection.moveTo(base, extent);

    return didFlipStartEnd ? !baseIsStart : baseIsStart;
}

- (BOOL)setSelectionWithBasePoint:(CGPoint)basePoint extentPoint:(CGPoint)extentPoint baseIsStart:(BOOL)baseIsStart
{
    return [self setSelectionWithBasePoint:basePoint extentPoint:extentPoint baseIsStart:baseIsStart allowFlipping:YES];
}

- (void)setSelectionWithFirstPoint:(CGPoint)firstPoint secondPoint:(CGPoint)secondPoint
{
    // We still support two-finger taps to make a selection, and these taps
    // don't care about base/extent.
    VisiblePosition first([self visiblePositionForPoint:firstPoint]);
    VisiblePosition second([self visiblePositionForPoint:secondPoint]);
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    frameSelection.moveTo(first, second);
}

- (void)ensureRangedSelectionContainsInitialStartPoint:(CGPoint)initialStartPoint initialEndPoint:(CGPoint)initialEndPoint
{
    // This method ensures that selection ends doesn't contract such that it no
    // longer contains these points. This is the desirable behavior when the
    // user does the tap-and-a-half + drag operation.
    Frame *frame = [self coreFrame];
    const VisibleSelection& originalSelection = frame->selection().selection();
    Position ensureStart([self visiblePositionForPoint:initialStartPoint].deepEquivalent());
    Position ensureEnd([self visiblePositionForPoint:initialEndPoint].deepEquivalent());
    if (originalSelection.start() > ensureStart)
        frame->selection().moveTo(ensureStart, originalSelection.end());
    else if (originalSelection.end() < ensureEnd)
        frame->selection().moveTo(originalSelection.start(), ensureEnd);
}

- (void)aggressivelyExpandSelectionToWordContainingCaretSelection
{
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    VisiblePosition end = frameSelection.selection().visibleEnd();
    if (end == endOfDocument(end) && end != startOfDocument(end) && end == startOfLine(end))
        frameSelection.moveTo(end.previous(), end);

    [self expandSelectionToWordContainingCaretSelection];

    // This is a temporary hack until we get the improvements
    // I'm working on for RTL selection.
    if (frameSelection.granularity() == WordGranularity)
        frameSelection.moveTo(frameSelection.selection().start(), frameSelection.selection().end());
    
    if (frameSelection.selection().isCaret()) {
        VisiblePosition pos(frameSelection.selection().end());
        if (isStartOfLine(pos) && isEndOfLine(pos)) {
            VisiblePosition next(pos.next());
            if (next.isNotNull())
                frameSelection.moveTo(end, next);
        }
        else {
            while (pos.isNotNull()) {
                VisiblePosition wordStart(startOfWord(pos));
                if (wordStart != pos) {
                    frameSelection.moveTo(wordStart, frameSelection.selection().end());
                    break;
                }
                pos = pos.previous();
            }
        }
    }
}

- (void)expandSelectionToSentence
{
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    VisiblePosition pos = frameSelection.selection().start();
    VisiblePosition start = startOfSentence(pos);
    VisiblePosition end = endOfSentence(pos);
    frameSelection.moveTo(start, end);
}

- (WKWritingDirection)selectionBaseWritingDirection
{
    Frame *frame = [self coreFrame];
    switch (frame->editor().baseWritingDirectionForSelectionStart()) {
    case WritingDirection::LeftToRight:
        return WKWritingDirectionLeftToRight;

    case WritingDirection::RightToLeft:
        return WKWritingDirectionRightToLeft;

    default:
        ASSERT_NOT_REACHED();
        break;
    }

    return WKWritingDirectionLeftToRight;
}

- (void)toggleBaseWritingDirection
{
    WKWritingDirection updated = WKWritingDirectionRightToLeft;
    switch ([self selectionBaseWritingDirection]) {
        case WKWritingDirectionLeftToRight:
            updated = WKWritingDirectionRightToLeft;
            break;
        case WKWritingDirectionRightToLeft:
            updated = WKWritingDirectionLeftToRight;
            break;
        default:
            // WebCore should never return anything else, including WKWritingDirectionNatural
            ASSERT_NOT_REACHED();
            break;
    }
    [self setBaseWritingDirection:updated];
}

- (void)setBaseWritingDirection:(WKWritingDirection)direction
{
    WKWritingDirection originalDirection = [self selectionBaseWritingDirection];

    Frame *frame = [self coreFrame];
    if (!frame->selection().selection().isContentEditable())
        return;
    
    auto wcDirection = WritingDirection::LeftToRight;
    switch (direction) {
        case WKWritingDirectionNatural:
            wcDirection = WritingDirection::Natural;
            break;
        case WKWritingDirectionLeftToRight:
            wcDirection = WritingDirection::LeftToRight;
            break;
        case WKWritingDirectionRightToLeft:
            wcDirection = WritingDirection::RightToLeft;
            break;
        default:
            ASSERT_NOT_REACHED();
            break;
    }
    frame->editor().setBaseWritingDirection(wcDirection);
    
    if (originalDirection != [self selectionBaseWritingDirection])
        frame->editor().setTextAlignmentForChangedBaseWritingDirection(wcDirection);
}

- (void)moveSelectionToStart
{
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    VisiblePosition start = startOfDocument(frameSelection.selection().start());
    frameSelection.moveTo(start);
}

- (void)moveSelectionToEnd
{
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    VisiblePosition end =  endOfDocument(frameSelection.selection().end());
    frameSelection.moveTo(end);
}

- (void)moveSelectionToPoint:(CGPoint)point
{
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    VisiblePosition pos = [self _visiblePositionForPoint:point];
    frameSelection.moveTo(pos);
}

- (void)setSelectionGranularity:(WebTextGranularity)granularity
{
    TextGranularity wcGranularity = CharacterGranularity;
    switch (granularity) {
        case WebTextGranularityCharacter:
            wcGranularity = CharacterGranularity;
            break;
        case WebTextGranularityWord:
            wcGranularity = WordGranularity;
            break;
        case WebTextGranularitySentence:
            wcGranularity = SentenceGranularity;
            break;
        case WebTextGranularityParagraph:
            wcGranularity = ParagraphGranularity;
            break;
        case WebTextGranularityAll:
            // FIXME: Add DocumentGranularity.
            wcGranularity = ParagraphGranularity;
            break;
        default:
            ASSERT_NOT_REACHED();
            break;
    }
    FrameSelection& frameSelection = _private->coreFrame->selection();
    frameSelection.setSelection(frameSelection.selection(), { }, { }, { }, wcGranularity);
}

static inline bool isAlphaNumericCharacter(UChar32 c)
{
    static CFCharacterSetRef set = CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric);
    return CFCharacterSetIsCharacterMember(set, c);
}

static VisiblePosition SimpleSmartExtendStart(const VisiblePosition& start, const VisiblePosition& end, const VisibleSelection& initialExtent)
{
    VisiblePosition pos(start);
    VisiblePosition initialStart;
    if (initialExtent.isCaretOrRange())
        initialStart = VisiblePosition(initialExtent.start(), initialExtent.affinity());

    if (initialStart == start) {
        // No smarts needed. Leave selection where it is.
        return pos;
    }

    UChar32 charBefore = pos.characterBefore();
    UChar32 charAfter = pos.characterAfter();
    if (isAlphaNumericCharacter(charAfter) && !isAlphaNumericCharacter(charBefore)) {
        // This is a word start. Leave selection where it is.
        return pos;
    }
    
    if (isAlphaNumericCharacter(charBefore) && !isAlphaNumericCharacter(charAfter)) {
        // This is a word end. Nudge the selection to the next character before proceeding.
        pos = pos.next();
    }

    // Extend to the start of the word.
    // If this isn't where the start was initially, use this position.
    VisiblePosition wordStart(startOfWord(pos));
    if (wordStart != initialStart) {
        return wordStart;
    }
    // Conversely, if the initial start equals the current word start, then
    // run the rest of this function to see if the selection should extend
    // back to the next word.

    // Passed-in end must be at least three characters from initialStart or
    // must cross word boundary.
    // If this is where the start was initially, skip to the end of the word,
    // then iterate forward in the document until we hit an alphanumeric.
    VisiblePosition wordEnd(endOfWord(pos));
    pos = wordEnd;
    while (pos.isNotNull() && !isStartOfLine(pos) && !isEndOfLine(pos) && pos != end) {
        UChar32 c = pos.characterAfter();
        if (isAlphaNumericCharacter(c))
            break;
        pos = pos.next();
    }
    
    // Don't let the smart extension make the start equal the end.
    // Expand out to word boundary.
    if (pos == end)
        pos = wordStart;
    return pos;
}

static VisiblePosition SimpleSmartExtendEnd(const VisiblePosition& start, const VisiblePosition& end, const VisibleSelection& initialExtent)
{
    VisiblePosition pos(end);

    VisiblePosition initialEnd;
    if (initialExtent.isCaretOrRange())
        initialEnd = VisiblePosition(initialExtent.end(), initialExtent.affinity());
    
    if (initialEnd == end) {
        // No smarts needed. Leave selection where it is.
        return pos;
    }
    
    UChar32 charBefore = pos.characterBefore();
    UChar32 charAfter = pos.characterAfter();
    if (isAlphaNumericCharacter(charBefore) && !isAlphaNumericCharacter(charAfter)) {
        // This is a word end. Leave selection where it is.
        return pos;
    }

    if (!isAlphaNumericCharacter(charBefore) && isAlphaNumericCharacter(charAfter)) {
        // This is a word start. Nudge the selection to the previous character before proceeding.
        pos = pos.previous();
    }

    // Extend to the end of the word.
    // If this isn't where the end was initially, use this position.
    VisiblePosition wordEnd(endOfWord(pos));
    if (wordEnd != initialEnd && isAlphaNumericCharacter(wordEnd.characterBefore())) {
        return wordEnd;
    }
    // Conversely, if the initial end equals the current word end, then
    // run the rest of this function to see if the selection should extend
    // back to the previous word.

    // If this is where the end was initially, skip to the start of the word,
    // then iterate backward in the document until we hit an alphanumeric.
    VisiblePosition wordStart(startOfWord(pos));
    pos = wordStart;
    while (pos.isNotNull() && !isStartOfLine(pos) && !isEndOfLine(pos) && pos != start) {
        UChar32 c = pos.characterBefore();
        if (isAlphaNumericCharacter(c))
            break;
        pos = pos.previous();
    }

    // Don't let the smart extension make the end equal the start.
    // Expand out to word boundary.
    if (pos == start)
        pos = wordEnd;
    
    return pos;
}

- (void)smartExtendRangedSelection:(WebTextSmartExtendDirection)direction
{
    if ([self selectionState] != WebTextSelectionStateRange)
        return;
    
    Frame *frame = [self coreFrame];
    FrameSelection& frameSelection = frame->selection();
    EAffinity affinity = frameSelection.selection().affinity();
    VisiblePosition start(frameSelection.selection().start(), affinity);
    VisiblePosition end(frameSelection.selection().end(), affinity);
    VisiblePosition base(frame->rangedSelectionBase().base());  // should equal start or end

    // Base must equal start or end
    if (base != start && base != end)
        return;

    VisiblePosition extent(frameSelection.selection().extent(), affinity);
    
    // We don't yet support smart extension for languages which
    // require context for word boundary.
    if (requiresContextForWordBoundary(extent.characterAfter()) || 
        requiresContextForWordBoundary(extent.characterBefore()))
        return;

    // If the smart-extend direction is neither left nor right, do
    // not pass rangedSelectionInitialExtent to the smart extend functions.
    // This will have the effect of always extending out to include the
    // word which contains the extent.
    VisibleSelection initialExtent;
    if (direction != WebTextSmartExtendDirectionNone)
        initialExtent = frame->rangedSelectionInitialExtent();

    VisiblePosition smartExtent;
    if (base == end) {  // extend start
        smartExtent = SimpleSmartExtendStart(start, end, initialExtent);
    }
    else {  // base == start / extend end
        smartExtent = SimpleSmartExtendEnd(start, end, initialExtent);
    }

    if (smartExtent.isNotNull() && smartExtent != extent)
        frameSelection.moveTo(base, smartExtent);

}

- (WebVisiblePosition *)startPosition
{
    Frame *frame = [self coreFrame];
    Element *rootElement = frame->document()->documentElement();
    return [WebVisiblePosition _wrapVisiblePosition:startOfDocument(static_cast<Node*>(rootElement))];
}

- (WebVisiblePosition *)endPosition
{
    Frame *frame = [self coreFrame];
    Element *rootElement = frame->document()->documentElement();
    return [WebVisiblePosition _wrapVisiblePosition:endOfDocument(static_cast<Node*>(rootElement))];
}

- (BOOL)renderedCharactersExceed:(NSUInteger)threshold
{
    Frame *frame = [self coreFrame];
    return frame->view()->renderedCharactersExceed(threshold);
}

// Iterates backward through the document and returns the point at which untouched dictation results end.
- (WebVisiblePosition *)previousUnperturbedDictationResultBoundaryFromPosition:(WebVisiblePosition *)position
{
    VisiblePosition currentVisiblePosition = [position _visiblePosition];
    if (currentVisiblePosition.isNull())
        return position;
    
    Document& document = currentVisiblePosition.deepEquivalent().anchorNode()->document();

    id uikitDelegate = [[self webView] _UIKitDelegate];
    if (![uikitDelegate respondsToSelector:@selector(isUnperturbedDictationResultMarker:)])
        return position;
    
    while (currentVisiblePosition.isNotNull()) {
        WebVisiblePosition *currentWebVisiblePosition = [WebVisiblePosition _wrapVisiblePosition:currentVisiblePosition];
        
        auto* currentNode = currentVisiblePosition.deepEquivalent().anchorNode();
        int lastOffset = lastOffsetForEditing(*currentNode);
        ASSERT(lastOffset >= 0);
        if (lastOffset < 0)
            return currentWebVisiblePosition;
        
        VisiblePosition previousVisiblePosition = currentVisiblePosition.previous();
        if (previousVisiblePosition.isNull())
            return currentWebVisiblePosition;
        
        auto graphemeRange = Range::create(document, previousVisiblePosition.deepEquivalent(), currentVisiblePosition.deepEquivalent());
        
        auto markers = document.markers().markersInRange(graphemeRange, DocumentMarker::DictationResult);
        if (markers.isEmpty())
            return currentWebVisiblePosition;
        
        // FIXME: Result markers should not overlap, so there should only ever be one for a single grapheme.
        // <rdar://problem/9810617> Too much document context is omitted when sending dictation hints because of problems with WebCore DocumentMarkers
        // ASSERT(markers.size() == 1);
        if (markers.size() > 1)
            return currentWebVisiblePosition;
        RenderedDocumentMarker* resultMarker = markers.at(0);
        
        // FIXME: WebCore doesn't always update markers correctly during editing. Bail if resultMarker extends off the edge of 
        // this node, because that means it's invalid.
        if (resultMarker->endOffset() > (unsigned)lastOffset)
            return currentWebVisiblePosition;
        
        if (![uikitDelegate isUnperturbedDictationResultMarker:resultMarker->metadata()])
            return currentWebVisiblePosition;
        
        if (resultMarker->startOffset() > 0)
            return [WebVisiblePosition _wrapVisiblePosition:VisiblePosition(createLegacyEditingPosition(currentNode, resultMarker->startOffset()))];
        
        currentVisiblePosition = VisiblePosition(createLegacyEditingPosition(currentNode, 0));
    }
    
    return position;
}

// Iterates forward through the document and returns the point at which untouched dictation results end.
- (WebVisiblePosition *)nextUnperturbedDictationResultBoundaryFromPosition:(WebVisiblePosition *)position
{
    VisiblePosition currentVisiblePosition = [position _visiblePosition];
    if (currentVisiblePosition.isNull())
        return position;
    
    Document& document = currentVisiblePosition.deepEquivalent().anchorNode()->document();
    
    id uikitDelegate = [[self webView] _UIKitDelegate];
    if (![uikitDelegate respondsToSelector:@selector(isUnperturbedDictationResultMarker:)])
        return position;
    
    while (currentVisiblePosition.isNotNull()) {
        WebVisiblePosition *currentWebVisiblePosition = [WebVisiblePosition _wrapVisiblePosition:currentVisiblePosition];
        
        auto* currentNode = currentVisiblePosition.deepEquivalent().anchorNode();
        int lastOffset = lastOffsetForEditing(*currentNode);
        ASSERT(lastOffset >= 0);
        if (lastOffset < 0)
            return currentWebVisiblePosition;
        
        VisiblePosition nextVisiblePosition = currentVisiblePosition.next();
        if (nextVisiblePosition.isNull())
            return currentWebVisiblePosition;
        
        auto graphemeRange = Range::create(document, currentVisiblePosition.deepEquivalent(), nextVisiblePosition.deepEquivalent());
        
        auto markers = document.markers().markersInRange(graphemeRange, DocumentMarker::DictationResult);
        if (markers.isEmpty())
            return currentWebVisiblePosition;
        
        // FIXME: Result markers should not overlap, so there should only ever be one for a single grapheme.
        // <rdar://problem/9810617> Too much document context is omitted when sending dictation hints because of problems with WebCore DocumentMarkers
        //ASSERT(markers.size() == 1);
        if (markers.size() > 1)
            return currentWebVisiblePosition;
        DocumentMarker* resultMarker = markers.at(0);
        
        // FIXME: WebCore doesn't always update markers correctly during editing. Bail if resultMarker extends off the edge of 
        // this node, because that means it's invalid.
        if (resultMarker->endOffset() > static_cast<unsigned>(lastOffset))
            return currentWebVisiblePosition;
        
        if (![uikitDelegate isUnperturbedDictationResultMarker:resultMarker->metadata()])
            return currentWebVisiblePosition;
        
        if (resultMarker->endOffset() <= static_cast<unsigned>(lastOffset))
            return [WebVisiblePosition _wrapVisiblePosition:VisiblePosition(createLegacyEditingPosition(currentNode, resultMarker->endOffset()))];
        
        currentVisiblePosition = VisiblePosition(createLegacyEditingPosition(currentNode, lastOffset));
    }
    
    return position;
}

- (CGRect)elementRectAtPoint:(CGPoint)point
{
    Frame *frame = [self coreFrame];
    IntPoint adjustedPoint = frame->view()->windowToContents(roundedIntPoint(point));
    HitTestResult result = frame->eventHandler().hitTestResultAtPoint(adjustedPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent);
    Node* hitNode = result.innerNode();
    if (!hitNode || !hitNode->renderer())
        return IntRect();
    return result.innerNodeFrame()->view()->contentsToWindow(hitNode->renderer()->absoluteBoundingBoxRect(true));
}

@end

#endif  // PLATFORM(IOS_FAMILY)
