/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/editing/selection_modifier.h"

#include "third_party/blink/renderer/core/editing/bidi_adjustment.h"
#include "third_party/blink/renderer/core/editing/editing_behavior.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/inline_box_position.h"
#include "third_party/blink/renderer/core/editing/local_caret_rect.h"
#include "third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
#include "third_party/blink/renderer/core/page/spatial_navigation.h"

namespace blink {

namespace {

// There are some cases where |SelectionModifier::ModifyWithPageGranularity()|
// enters an infinite loop. Work around it by hard-limiting the iteration.
const unsigned kMaxIterationForPageGranularityMovement = 1024;

VisiblePositionInFlatTree LeftBoundaryOfLine(const VisiblePositionInFlatTree& c,
                                             TextDirection direction) {
  DCHECK(c.IsValid()) << c;
  return direction == TextDirection::kLtr ? LogicalStartOfLine(c)
                                          : LogicalEndOfLine(c);
}

VisiblePositionInFlatTree RightBoundaryOfLine(
    const VisiblePositionInFlatTree& c,
    TextDirection direction) {
  DCHECK(c.IsValid()) << c;
  return direction == TextDirection::kLtr ? LogicalEndOfLine(c)
                                          : LogicalStartOfLine(c);
}

}  // namespace

static bool InSameParagraph(const VisiblePositionInFlatTree& a,
                            const VisiblePositionInFlatTree& b,
                            EditingBoundaryCrossingRule boundary_crossing_rule =
                                kCannotCrossEditingBoundary) {
  DCHECK(a.IsValid()) << a;
  DCHECK(b.IsValid()) << b;
  return a.IsNotNull() &&
         StartOfParagraph(a, boundary_crossing_rule).DeepEquivalent() ==
             StartOfParagraph(b, boundary_crossing_rule).DeepEquivalent();
}

// static
VisiblePositionInFlatTree SelectionModifier::PreviousParagraphPosition(
    const VisiblePositionInFlatTree& passed_position,
    LayoutUnit x_point) {
  VisiblePositionInFlatTree position = passed_position;
  do {
    DCHECK(position.IsValid()) << position;
    const VisiblePositionInFlatTree& new_position = CreateVisiblePosition(
        PreviousLinePosition(position.ToPositionWithAffinity(), x_point));
    if (new_position.IsNull() ||
        new_position.DeepEquivalent() == position.DeepEquivalent())
      break;
    position = new_position;
  } while (InSameParagraph(passed_position, position));
  return position;
}

// static
VisiblePositionInFlatTree SelectionModifier::NextParagraphPosition(
    const VisiblePositionInFlatTree& passed_position,
    LayoutUnit x_point) {
  VisiblePositionInFlatTree position = passed_position;
  do {
    DCHECK(position.IsValid()) << position;
    const VisiblePositionInFlatTree& new_position = CreateVisiblePosition(
        NextLinePosition(position.ToPositionWithAffinity(), x_point));
    if (new_position.IsNull() ||
        new_position.DeepEquivalent() == position.DeepEquivalent())
      break;
    position = new_position;
  } while (InSameParagraph(passed_position, position));
  return position;
}

LayoutUnit NoXPosForVerticalArrowNavigation() {
  return LayoutUnit::Min();
}

bool SelectionModifier::ShouldAlwaysUseDirectionalSelection(
    const LocalFrame& frame) {
  return frame.GetEditor().Behavior().ShouldConsiderSelectionAsDirectional();
}

SelectionModifier::SelectionModifier(
    const LocalFrame& frame,
    const SelectionInDOMTree& selection,
    LayoutUnit x_pos_for_vertical_arrow_navigation)
    : frame_(&frame),
      current_selection_(ConvertToSelectionInFlatTree(selection)),
      x_pos_for_vertical_arrow_navigation_(
          x_pos_for_vertical_arrow_navigation) {}

SelectionModifier::SelectionModifier(const LocalFrame& frame,
                                     const SelectionInDOMTree& selection)
    : SelectionModifier(frame, selection, NoXPosForVerticalArrowNavigation()) {}

VisibleSelection SelectionModifier::Selection() const {
  return CreateVisibleSelection(
      ConvertToSelectionInDOMTree(current_selection_));
}

static VisiblePositionInFlatTree ComputeVisibleExtent(
    const VisibleSelectionInFlatTree& visible_selection) {
  return CreateVisiblePosition(visible_selection.Extent(),
                               visible_selection.Affinity());
}

TextDirection SelectionModifier::DirectionOfEnclosingBlock() const {
  const PositionInFlatTree& selection_extent = selection_.Extent();

  // TODO(editing-dev): Check for PositionInFlatTree::IsNotNull is an easy fix
  // for few editing/ web tests, that didn't expect that (e.g.
  // editing/selection/extend-byline-withfloat.html).
  // That should be fixed in a more appropriate manner.
  // We should either have SelectionModifier aborted earlier for null selection,
  // or do not allow null selection in SelectionModifier at all.
  return selection_extent.IsNotNull()
             ? DirectionOfEnclosingBlockOf(selection_extent)
             : TextDirection::kLtr;
}

namespace {

base::Optional<TextDirection> DirectionAt(
    const PositionInFlatTreeWithAffinity& position) {
  if (position.IsNull())
    return base::nullopt;
  const PositionInFlatTreeWithAffinity adjusted =
      ComputeInlineAdjustedPosition(position);
  if (adjusted.IsNull())
    return base::nullopt;

  if (NGInlineFormattingContextOf(adjusted.GetPosition())) {
    const NGInlineCursor& cursor = ComputeNGCaretPosition(adjusted).cursor;
    if (cursor)
      return cursor.Current().ResolvedDirection();
    return base::nullopt;
  }

  if (const InlineBox* box =
          ComputeInlineBoxPositionForInlineAdjustedPosition(adjusted)
              .inline_box)
    return box->Direction();
  return base::nullopt;
}

// TODO(xiaochengh): Deduplicate code with |DirectionAt()|.
base::Optional<TextDirection> LineDirectionAt(
    const PositionInFlatTreeWithAffinity& position) {
  if (position.IsNull())
    return base::nullopt;
  const PositionInFlatTreeWithAffinity adjusted =
      ComputeInlineAdjustedPosition(position);
  if (adjusted.IsNull())
    return base::nullopt;

  if (NGInlineFormattingContextOf(adjusted.GetPosition())) {
    NGInlineCursor line = ComputeNGCaretPosition(adjusted).cursor;
    if (!line)
      return base::nullopt;
    line.MoveToContainingLine();
    return line.Current().BaseDirection();
  }

  if (const InlineBox* box =
          ComputeInlineBoxPositionForInlineAdjustedPosition(adjusted)
              .inline_box) {
    return ParagraphDirectionOf(*box);
  }
  return base::nullopt;
}

TextDirection DirectionOf(const VisibleSelectionInFlatTree& visible_selection) {
  base::Optional<TextDirection> maybe_start_direction =
      DirectionAt(visible_selection.VisibleStart().ToPositionWithAffinity());
  base::Optional<TextDirection> maybe_end_direction =
      DirectionAt(visible_selection.VisibleEnd().ToPositionWithAffinity());
  if (maybe_start_direction.has_value() && maybe_end_direction.has_value() &&
      maybe_start_direction.value() == maybe_end_direction.value())
    return maybe_start_direction.value();

  return DirectionOfEnclosingBlockOf(visible_selection.Extent());
}

}  // namespace

TextDirection SelectionModifier::DirectionOfSelection() const {
  return DirectionOf(selection_);
}

TextDirection SelectionModifier::LineDirectionOfExtent() const {
  return LineDirectionAt(selection_.VisibleExtent().ToPositionWithAffinity())
      .value_or(DirectionOfEnclosingBlockOf(selection_.Extent()));
}

static bool IsBaseStart(const VisibleSelectionInFlatTree& visible_selection,
                        SelectionModifyDirection direction) {
  switch (direction) {
    case SelectionModifyDirection::kRight:
      return DirectionOf(visible_selection) == TextDirection::kLtr;
    case SelectionModifyDirection::kForward:
      return true;
    case SelectionModifyDirection::kLeft:
      return DirectionOf(visible_selection) != TextDirection::kLtr;
    case SelectionModifyDirection::kBackward:
      return false;
  }
  NOTREACHED() << "We should handle " << static_cast<int>(direction);
  return true;
}

// This function returns |VisibleSelectionInFlatTree| from start and end
// position of current_selection_'s |VisibleSelectionInFlatTree| with
// |direction| and ordering of base and extent to handle base/extent don't match
// to start/end, e.g. granularity
// != character, and start/end adjustment in
// |VisibleSelectionInFlatTree::validate()| for range selection.
VisibleSelectionInFlatTree SelectionModifier::PrepareToModifySelection(
    SelectionModifyAlteration alter,
    SelectionModifyDirection direction) const {
  const VisibleSelectionInFlatTree& visible_selection =
      CreateVisibleSelection(current_selection_);
  if (alter != SelectionModifyAlteration::kExtend)
    return visible_selection;
  if (visible_selection.IsNone())
    return visible_selection;

  const EphemeralRangeInFlatTree& range =
      visible_selection.AsSelection().ComputeRange();
  if (range.IsCollapsed())
    return visible_selection;
  SelectionInFlatTree::Builder builder;
  // Make base and extent match start and end so we extend the user-visible
  // selection. This only matters for cases where base and extend point to
  // different positions than start and end (e.g. after a double-click to
  // select a word).
  const bool base_is_start = selection_is_directional_
                                 ? visible_selection.IsBaseFirst()
                                 : IsBaseStart(visible_selection, direction);
  if (base_is_start)
    builder.SetAsForwardSelection(range);
  else
    builder.SetAsBackwardSelection(range);
  return CreateVisibleSelection(builder.Build());
}

VisiblePositionInFlatTree SelectionModifier::PositionForPlatform(
    bool is_get_start) const {
  Settings* settings = GetFrame().GetSettings();
  if (settings && settings->GetEditingBehaviorType() ==
                      mojom::blink::EditingBehavior::kEditingMacBehavior)
    return is_get_start ? selection_.VisibleStart() : selection_.VisibleEnd();
  // Linux and Windows always extend selections from the extent endpoint.
  // FIXME: VisibleSelectionInFlatTree should be fixed to ensure as an invariant
  // that base/extent always point to the same nodes as start/end, but which
  // points to which depends on the value of isBaseFirst. Then this can be
  // changed to just return selection_.extent().
  return selection_.IsBaseFirst() ? selection_.VisibleEnd()
                                  : selection_.VisibleStart();
}

VisiblePositionInFlatTree SelectionModifier::StartForPlatform() const {
  return PositionForPlatform(true);
}

VisiblePositionInFlatTree SelectionModifier::EndForPlatform() const {
  return PositionForPlatform(false);
}

PositionInFlatTree SelectionModifier::NextWordPositionForPlatform(
    const PositionInFlatTree& original_position) {
  const PlatformWordBehavior platform_word_behavior =
      GetFrame().GetEditor().Behavior().ShouldSkipSpaceWhenMovingRight()
          ? PlatformWordBehavior::kWordSkipSpaces
          : PlatformWordBehavior::kWordDontSkipSpaces;
  // Next word position can't be upstream.
  const PositionInFlatTree position_after_current_word =
      NextWordPosition(original_position, platform_word_behavior).GetPosition();

  return position_after_current_word;
}

static VisiblePositionInFlatTree AdjustForwardPositionForUserSelectAll(
    const VisiblePositionInFlatTree& position) {
  Node* const root_user_select_all = EditingStrategy::RootUserSelectAllForNode(
      position.DeepEquivalent().AnchorNode());
  if (!root_user_select_all)
    return position;
  return CreateVisiblePosition(MostForwardCaretPosition(
      PositionInFlatTree::AfterNode(*root_user_select_all),
      kCanCrossEditingBoundary));
}

static VisiblePositionInFlatTree AdjustBackwardPositionForUserSelectAll(
    const VisiblePositionInFlatTree& position) {
  Node* const root_user_select_all = EditingStrategy::RootUserSelectAllForNode(
      position.DeepEquivalent().AnchorNode());
  if (!root_user_select_all)
    return position;
  return CreateVisiblePosition(MostBackwardCaretPosition(
      PositionInFlatTree::BeforeNode(*root_user_select_all),
      kCanCrossEditingBoundary));
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingRightInternal(
    TextGranularity granularity) {
  // The difference between modifyExtendingRight and modifyExtendingForward is:
  // modifyExtendingForward always extends forward logically.
  // modifyExtendingRight behaves the same as modifyExtendingForward except for
  // extending character or word, it extends forward logically if the enclosing
  // block is LTR direction, but it extends backward logically if the enclosing
  // block is RTL direction.
  switch (granularity) {
    case TextGranularity::kCharacter:
      if (DirectionOfEnclosingBlock() == TextDirection::kLtr) {
        return NextPositionOf(ComputeVisibleExtent(selection_),
                              kCanSkipOverEditingBoundary);
      }
      return PreviousPositionOf(ComputeVisibleExtent(selection_),
                                kCanSkipOverEditingBoundary);
    case TextGranularity::kWord:
      if (DirectionOfEnclosingBlock() == TextDirection::kLtr) {
        return CreateVisiblePosition(NextWordPositionForPlatform(
            ComputeVisibleExtent(selection_).DeepEquivalent()));
      }
      return CreateVisiblePosition(PreviousWordPosition(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
    case TextGranularity::kLineBoundary:
      if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
        return ModifyExtendingForwardInternal(granularity);
      return ModifyExtendingBackwardInternal(granularity);
    case TextGranularity::kSentence:
    case TextGranularity::kLine:
    case TextGranularity::kParagraph:
    case TextGranularity::kSentenceBoundary:
    case TextGranularity::kParagraphBoundary:
    case TextGranularity::kDocumentBoundary:
      // TODO(editing-dev): implement all of the above?
      return ModifyExtendingForwardInternal(granularity);
  }
  NOTREACHED() << static_cast<int>(granularity);
  return VisiblePositionInFlatTree();
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingRight(
    TextGranularity granularity) {
  const VisiblePositionInFlatTree& pos =
      ModifyExtendingRightInternal(granularity);
  if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
    return AdjustForwardPositionForUserSelectAll(pos);
  return AdjustBackwardPositionForUserSelectAll(pos);
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingForwardInternal(
    TextGranularity granularity) {
  switch (granularity) {
    case TextGranularity::kCharacter:
      return NextPositionOf(ComputeVisibleExtent(selection_),
                            kCanSkipOverEditingBoundary);
    case TextGranularity::kWord:
      return CreateVisiblePosition(NextWordPositionForPlatform(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
    case TextGranularity::kSentence:
      return CreateVisiblePosition(
          NextSentencePosition(
              ComputeVisibleExtent(selection_).DeepEquivalent()),
          TextAffinity::kUpstreamIfPossible);
    case TextGranularity::kLine: {
      const VisiblePositionInFlatTree& pos = ComputeVisibleExtent(selection_);
      DCHECK(pos.IsValid()) << pos;
      return CreateVisiblePosition(NextLinePosition(
          pos.ToPositionWithAffinity(),
          LineDirectionPointForBlockDirectionNavigation(selection_.Extent())));
    }
    case TextGranularity::kParagraph:
      return NextParagraphPosition(
          ComputeVisibleExtent(selection_),
          LineDirectionPointForBlockDirectionNavigation(selection_.Extent()));
    case TextGranularity::kSentenceBoundary:
      return EndOfSentence(EndForPlatform());
    case TextGranularity::kLineBoundary:
      return LogicalEndOfLine(EndForPlatform());
    case TextGranularity::kParagraphBoundary:
      return EndOfParagraph(EndForPlatform());
    case TextGranularity::kDocumentBoundary: {
      const VisiblePositionInFlatTree& pos = EndForPlatform();
      if (IsEditablePosition(pos.DeepEquivalent())) {
        DCHECK(pos.IsValid()) << pos;
        return CreateVisiblePosition(
            EndOfEditableContent(pos.DeepEquivalent()));
      }
      return EndOfDocument(pos);
    }
  }
  NOTREACHED() << static_cast<int>(granularity);
  return VisiblePositionInFlatTree();
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingForward(
    TextGranularity granularity) {
  const VisiblePositionInFlatTree pos =
      ModifyExtendingForwardInternal(granularity);
  if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
    return AdjustForwardPositionForUserSelectAll(pos);
  return AdjustBackwardPositionForUserSelectAll(pos);
}

VisiblePositionInFlatTree SelectionModifier::ModifyMovingRight(
    TextGranularity granularity) {
  switch (granularity) {
    case TextGranularity::kCharacter:
      if (!selection_.IsRange()) {
        if (LineDirectionOfExtent() == TextDirection::kLtr)
          return ModifyMovingForward(granularity);
        return ModifyMovingBackward(granularity);
      }
      if (DirectionOfSelection() == TextDirection::kLtr)
        return CreateVisiblePosition(selection_.End(), selection_.Affinity());
      return CreateVisiblePosition(selection_.Start(), selection_.Affinity());
    case TextGranularity::kWord:
      if (LineDirectionOfExtent() == TextDirection::kLtr)
        return ModifyMovingForward(granularity);
      return ModifyMovingBackward(granularity);
    case TextGranularity::kSentence:
    case TextGranularity::kLine:
    case TextGranularity::kParagraph:
    case TextGranularity::kSentenceBoundary:
    case TextGranularity::kParagraphBoundary:
    case TextGranularity::kDocumentBoundary:
      // TODO(editing-dev): Implement all of the above.
      return ModifyMovingForward(granularity);
    case TextGranularity::kLineBoundary:
      return RightBoundaryOfLine(StartForPlatform(),
                                 DirectionOfEnclosingBlock());
  }
  NOTREACHED() << static_cast<int>(granularity);
  return VisiblePositionInFlatTree();
}

VisiblePositionInFlatTree SelectionModifier::ModifyMovingForward(
    TextGranularity granularity) {
  // TODO(editing-dev): Stay in editable content for the less common
  // granularities.
  switch (granularity) {
    case TextGranularity::kCharacter:
      if (selection_.IsRange())
        return CreateVisiblePosition(selection_.End(), selection_.Affinity());
      return NextPositionOf(ComputeVisibleExtent(selection_),
                            kCanSkipOverEditingBoundary);
    case TextGranularity::kWord:
      return CreateVisiblePosition(NextWordPositionForPlatform(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
    case TextGranularity::kSentence:
      return CreateVisiblePosition(
          NextSentencePosition(
              ComputeVisibleExtent(selection_).DeepEquivalent()),
          TextAffinity::kUpstreamIfPossible);
    case TextGranularity::kLine: {
      // down-arrowing from a range selection that ends at the start of a line
      // needs to leave the selection at that line start (no need to call
      // nextLinePosition!)
      const VisiblePositionInFlatTree& pos = EndForPlatform();
      if (selection_.IsRange() && IsStartOfLine(pos))
        return pos;
      DCHECK(pos.IsValid()) << pos;
      return CreateVisiblePosition(NextLinePosition(
          pos.ToPositionWithAffinity(),
          LineDirectionPointForBlockDirectionNavigation(selection_.Start())));
    }
    case TextGranularity::kParagraph:
      return NextParagraphPosition(
          EndForPlatform(),
          LineDirectionPointForBlockDirectionNavigation(selection_.Start()));
    case TextGranularity::kSentenceBoundary:
      return EndOfSentence(EndForPlatform());
    case TextGranularity::kLineBoundary:
      return LogicalEndOfLine(EndForPlatform());
    case TextGranularity::kParagraphBoundary:
      return EndOfParagraph(EndForPlatform());
    case TextGranularity::kDocumentBoundary: {
      const VisiblePositionInFlatTree& pos = EndForPlatform();
      if (IsEditablePosition(pos.DeepEquivalent())) {
        DCHECK(pos.IsValid()) << pos;
        return CreateVisiblePosition(
            EndOfEditableContent(pos.DeepEquivalent()));
      }
      return EndOfDocument(pos);
    }
  }
  NOTREACHED() << static_cast<int>(granularity);
  return VisiblePositionInFlatTree();
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingLeftInternal(
    TextGranularity granularity) {
  // The difference between modifyExtendingLeft and modifyExtendingBackward is:
  // modifyExtendingBackward always extends backward logically.
  // modifyExtendingLeft behaves the same as modifyExtendingBackward except for
  // extending character or word, it extends backward logically if the enclosing
  // block is LTR direction, but it extends forward logically if the enclosing
  // block is RTL direction.
  switch (granularity) {
    case TextGranularity::kCharacter:
      if (DirectionOfEnclosingBlock() == TextDirection::kLtr) {
        return PreviousPositionOf(ComputeVisibleExtent(selection_),
                                  kCanSkipOverEditingBoundary);
      }
      return NextPositionOf(ComputeVisibleExtent(selection_),
                            kCanSkipOverEditingBoundary);
    case TextGranularity::kWord:
      if (DirectionOfEnclosingBlock() == TextDirection::kLtr) {
        return CreateVisiblePosition(PreviousWordPosition(
            ComputeVisibleExtent(selection_).DeepEquivalent()));
      }
      return CreateVisiblePosition(NextWordPositionForPlatform(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
    case TextGranularity::kLineBoundary:
      if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
        return ModifyExtendingBackwardInternal(granularity);
      return ModifyExtendingForwardInternal(granularity);
    case TextGranularity::kSentence:
    case TextGranularity::kLine:
    case TextGranularity::kParagraph:
    case TextGranularity::kSentenceBoundary:
    case TextGranularity::kParagraphBoundary:
    case TextGranularity::kDocumentBoundary:
      return ModifyExtendingBackwardInternal(granularity);
  }
  NOTREACHED() << static_cast<int>(granularity);
  return VisiblePositionInFlatTree();
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingLeft(
    TextGranularity granularity) {
  const VisiblePositionInFlatTree& pos =
      ModifyExtendingLeftInternal(granularity);
  if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
    return AdjustBackwardPositionForUserSelectAll(pos);
  return AdjustForwardPositionForUserSelectAll(pos);
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingBackwardInternal(
    TextGranularity granularity) {
  // Extending a selection backward by word or character from just after a table
  // selects the table.  This "makes sense" from the user perspective, esp. when
  // deleting. It was done here instead of in VisiblePositionInFlatTree because
  // we want VPs to iterate over everything.
  switch (granularity) {
    case TextGranularity::kCharacter:
      return PreviousPositionOf(ComputeVisibleExtent(selection_),
                                kCanSkipOverEditingBoundary);
    case TextGranularity::kWord:
      return CreateVisiblePosition(PreviousWordPosition(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
    case TextGranularity::kSentence:
      return CreateVisiblePosition(PreviousSentencePosition(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
    case TextGranularity::kLine: {
      const VisiblePositionInFlatTree& pos = ComputeVisibleExtent(selection_);
      DCHECK(pos.IsValid()) << pos;
      return CreateVisiblePosition(PreviousLinePosition(
          pos.ToPositionWithAffinity(),
          LineDirectionPointForBlockDirectionNavigation(selection_.Extent())));
    }
    case TextGranularity::kParagraph:
      return PreviousParagraphPosition(
          ComputeVisibleExtent(selection_),
          LineDirectionPointForBlockDirectionNavigation(selection_.Extent()));
    case TextGranularity::kSentenceBoundary:
      return CreateVisiblePosition(
          StartOfSentencePosition(StartForPlatform().DeepEquivalent()));
    case TextGranularity::kLineBoundary:
      return LogicalStartOfLine(StartForPlatform());
    case TextGranularity::kParagraphBoundary:
      return StartOfParagraph(StartForPlatform());
    case TextGranularity::kDocumentBoundary: {
      const VisiblePositionInFlatTree pos = StartForPlatform();
      if (IsEditablePosition(pos.DeepEquivalent())) {
        DCHECK(pos.IsValid()) << pos;
        return CreateVisiblePosition(
            StartOfEditableContent(pos.DeepEquivalent()));
      }
      return CreateVisiblePosition(StartOfDocument(pos.DeepEquivalent()));
    }
  }
  NOTREACHED() << static_cast<int>(granularity);
  return VisiblePositionInFlatTree();
}

VisiblePositionInFlatTree SelectionModifier::ModifyExtendingBackward(
    TextGranularity granularity) {
  const VisiblePositionInFlatTree pos =
      ModifyExtendingBackwardInternal(granularity);
  if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
    return AdjustBackwardPositionForUserSelectAll(pos);
  return AdjustForwardPositionForUserSelectAll(pos);
}

VisiblePositionInFlatTree SelectionModifier::ModifyMovingLeft(
    TextGranularity granularity) {
  switch (granularity) {
    case TextGranularity::kCharacter:
      if (!selection_.IsRange()) {
        if (LineDirectionOfExtent() == TextDirection::kLtr)
          return ModifyMovingBackward(granularity);
        return ModifyMovingForward(granularity);
      }
      if (DirectionOfSelection() == TextDirection::kLtr)
        return CreateVisiblePosition(selection_.Start(), selection_.Affinity());
      return CreateVisiblePosition(selection_.End(), selection_.Affinity());
    case TextGranularity::kWord:
      if (LineDirectionOfExtent() == TextDirection::kLtr)
        return ModifyMovingBackward(granularity);
      return ModifyMovingForward(granularity);
    case TextGranularity::kSentence:
    case TextGranularity::kLine:
    case TextGranularity::kParagraph:
    case TextGranularity::kSentenceBoundary:
    case TextGranularity::kParagraphBoundary:
    case TextGranularity::kDocumentBoundary:
      // FIXME: Implement all of the above.
      return ModifyMovingBackward(granularity);
    case TextGranularity::kLineBoundary:
      return LeftBoundaryOfLine(StartForPlatform(),
                                DirectionOfEnclosingBlock());
  }
  NOTREACHED() << static_cast<int>(granularity);
  return VisiblePositionInFlatTree();
}

VisiblePositionInFlatTree SelectionModifier::ModifyMovingBackward(
    TextGranularity granularity) {
  VisiblePositionInFlatTree pos;
  switch (granularity) {
    case TextGranularity::kCharacter:
      if (selection_.IsRange()) {
        pos = CreateVisiblePosition(selection_.Start(), selection_.Affinity());
      } else {
        pos = PreviousPositionOf(ComputeVisibleExtent(selection_),
                                 kCanSkipOverEditingBoundary);
      }
      break;
    case TextGranularity::kWord:
      pos = CreateVisiblePosition(PreviousWordPosition(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
      break;
    case TextGranularity::kSentence:
      pos = CreateVisiblePosition(PreviousSentencePosition(
          ComputeVisibleExtent(selection_).DeepEquivalent()));
      break;
    case TextGranularity::kLine: {
      const VisiblePositionInFlatTree& start = StartForPlatform();
      DCHECK(start.IsValid()) << start;
      pos = CreateVisiblePosition(PreviousLinePosition(
          start.ToPositionWithAffinity(),
          LineDirectionPointForBlockDirectionNavigation(selection_.Start())));
      break;
    }
    case TextGranularity::kParagraph:
      pos = PreviousParagraphPosition(
          StartForPlatform(),
          LineDirectionPointForBlockDirectionNavigation(selection_.Start()));
      break;
    case TextGranularity::kSentenceBoundary:
      pos = CreateVisiblePosition(
          StartOfSentencePosition(StartForPlatform().DeepEquivalent()));
      break;
    case TextGranularity::kLineBoundary:
      pos = LogicalStartOfLine(StartForPlatform());
      break;
    case TextGranularity::kParagraphBoundary:
      pos = StartOfParagraph(StartForPlatform());
      break;
    case TextGranularity::kDocumentBoundary:
      pos = StartForPlatform();
      if (IsEditablePosition(pos.DeepEquivalent())) {
        DCHECK(pos.IsValid()) << pos;
        pos =
            CreateVisiblePosition(StartOfEditableContent(pos.DeepEquivalent()));
      } else {
        pos = CreateVisiblePosition(StartOfDocument(pos.DeepEquivalent()));
      }
      break;
  }
  return pos;
}

static bool IsBoundary(TextGranularity granularity) {
  return granularity == TextGranularity::kLineBoundary ||
         granularity == TextGranularity::kParagraphBoundary ||
         granularity == TextGranularity::kDocumentBoundary;
}

VisiblePositionInFlatTree SelectionModifier::ComputeModifyPosition(
    SelectionModifyAlteration alter,
    SelectionModifyDirection direction,
    TextGranularity granularity) {
  switch (direction) {
    case SelectionModifyDirection::kRight:
      if (alter == SelectionModifyAlteration::kMove)
        return ModifyMovingRight(granularity);
      return ModifyExtendingRight(granularity);
    case SelectionModifyDirection::kForward:
      if (alter == SelectionModifyAlteration::kExtend)
        return ModifyExtendingForward(granularity);
      return ModifyMovingForward(granularity);
    case SelectionModifyDirection::kLeft:
      if (alter == SelectionModifyAlteration::kMove)
        return ModifyMovingLeft(granularity);
      return ModifyExtendingLeft(granularity);
    case SelectionModifyDirection::kBackward:
      if (alter == SelectionModifyAlteration::kExtend)
        return ModifyExtendingBackward(granularity);
      return ModifyMovingBackward(granularity);
  }
  NOTREACHED() << static_cast<int>(direction);
  return VisiblePositionInFlatTree();
}

bool SelectionModifier::Modify(SelectionModifyAlteration alter,
                               SelectionModifyDirection direction,
                               TextGranularity granularity) {
  DCHECK(!GetFrame().GetDocument()->NeedsLayoutTreeUpdate());
  DocumentLifecycle::DisallowTransitionScope disallow_transition(
      GetFrame().GetDocument()->Lifecycle());

  selection_ = PrepareToModifySelection(alter, direction);
  if (selection_.IsNone())
    return false;

  bool was_range = selection_.IsRange();
  VisiblePositionInFlatTree original_start_position = selection_.VisibleStart();
  VisiblePositionInFlatTree position =
      ComputeModifyPosition(alter, direction, granularity);
  if (position.IsNull())
    return false;

  if (IsSpatialNavigationEnabled(&GetFrame())) {
    if (!was_range && alter == SelectionModifyAlteration::kMove &&
        position.DeepEquivalent() == original_start_position.DeepEquivalent())
      return false;
  }

  // Some of the above operations set an xPosForVerticalArrowNavigation.
  // Setting a selection will clear it, so save it to possibly restore later.
  // Note: the START position type is arbitrary because it is unused, it would
  // be the requested position type if there were no
  // xPosForVerticalArrowNavigation set.
  LayoutUnit x =
      LineDirectionPointForBlockDirectionNavigation(selection_.Start());

  switch (alter) {
    case SelectionModifyAlteration::kMove:
      current_selection_ = SelectionInFlatTree::Builder()
                               .Collapse(position.ToPositionWithAffinity())
                               .Build();
      break;
    case SelectionModifyAlteration::kExtend:

      if (!selection_.IsCaret() &&
          (granularity == TextGranularity::kWord ||
           granularity == TextGranularity::kParagraph ||
           granularity == TextGranularity::kLine) &&
          !GetFrame()
               .GetEditor()
               .Behavior()
               .ShouldExtendSelectionByWordOrLineAcrossCaret()) {
        // Don't let the selection go across the base position directly. Needed
        // to match mac behavior when, for instance, word-selecting backwards
        // starting with the caret in the middle of a word and then
        // word-selecting forward, leaving the caret in the same place where it
        // was, instead of directly selecting to the end of the word.
        const VisibleSelectionInFlatTree& new_selection =
            CreateVisibleSelection(
                SelectionInFlatTree::Builder(selection_.AsSelection())
                    .Extend(position.DeepEquivalent())
                    .Build());
        if (selection_.IsBaseFirst() != new_selection.IsBaseFirst())
          position = selection_.VisibleBase();
      }

      // Standard Mac behavior when extending to a boundary is grow the
      // selection rather than leaving the base in place and moving the
      // extent. Matches NSTextView.
      if (!GetFrame()
               .GetEditor()
               .Behavior()
               .ShouldAlwaysGrowSelectionWhenExtendingToBoundary() ||
          selection_.IsCaret() || !IsBoundary(granularity)) {
        current_selection_ = SelectionInFlatTree::Builder()
                                 .Collapse(selection_.Base())
                                 .Extend(position.DeepEquivalent())
                                 .Build();
      } else {
        TextDirection text_direction = DirectionOfEnclosingBlock();
        if (direction == SelectionModifyDirection::kForward ||
            (text_direction == TextDirection::kLtr &&
             direction == SelectionModifyDirection::kRight) ||
            (text_direction == TextDirection::kRtl &&
             direction == SelectionModifyDirection::kLeft)) {
          current_selection_ =
              SelectionInFlatTree::Builder()
                  .Collapse(selection_.IsBaseFirst()
                                ? selection_.Base()
                                : position.DeepEquivalent())
                  .Extend(selection_.IsBaseFirst() ? position.DeepEquivalent()
                                                   : selection_.Extent())
                  .Build();
        } else {
          current_selection_ =
              SelectionInFlatTree::Builder()
                  .Collapse(selection_.IsBaseFirst() ? position.DeepEquivalent()
                                                     : selection_.Base())
                  .Extend(selection_.IsBaseFirst() ? selection_.Extent()
                                                   : position.DeepEquivalent())
                  .Build();
        }
      }
      break;
  }

  if (granularity == TextGranularity::kLine ||
      granularity == TextGranularity::kParagraph)
    x_pos_for_vertical_arrow_navigation_ = x;

  return true;
}

// TODO(yosin): Maybe baseline would be better?
static bool AbsoluteCaretY(const PositionInFlatTreeWithAffinity& c, int& y) {
  IntRect rect = AbsoluteCaretBoundsOf(c);
  if (rect.IsEmpty())
    return false;
  y = rect.Y() + rect.Height() / 2;
  return true;
}

bool SelectionModifier::ModifyWithPageGranularity(
    SelectionModifyAlteration alter,
    unsigned vertical_distance,
    SelectionModifyVerticalDirection direction) {
  if (!vertical_distance)
    return false;

  DCHECK(!GetFrame().GetDocument()->NeedsLayoutTreeUpdate());
  DocumentLifecycle::DisallowTransitionScope disallow_transition(
      GetFrame().GetDocument()->Lifecycle());

  selection_ = PrepareToModifySelection(
      alter, direction == SelectionModifyVerticalDirection::kUp
                 ? SelectionModifyDirection::kBackward
                 : SelectionModifyDirection::kForward);

  VisiblePositionInFlatTree pos;
  LayoutUnit x_pos;
  switch (alter) {
    case SelectionModifyAlteration::kMove:
      pos = CreateVisiblePosition(
          direction == SelectionModifyVerticalDirection::kUp
              ? selection_.Start()
              : selection_.End(),
          selection_.Affinity());
      x_pos = LineDirectionPointForBlockDirectionNavigation(
          direction == SelectionModifyVerticalDirection::kUp
              ? selection_.Start()
              : selection_.End());
      break;
    case SelectionModifyAlteration::kExtend:
      pos = ComputeVisibleExtent(selection_);
      x_pos =
          LineDirectionPointForBlockDirectionNavigation(selection_.Extent());
      break;
  }

  int start_y;
  DCHECK(pos.IsValid()) << pos;
  if (!AbsoluteCaretY(pos.ToPositionWithAffinity(), start_y))
    return false;
  if (direction == SelectionModifyVerticalDirection::kUp)
    start_y = -start_y;
  int last_y = start_y;

  VisiblePositionInFlatTree result;
  VisiblePositionInFlatTree next;
  unsigned iteration_count = 0;
  for (VisiblePositionInFlatTree p = pos;
       iteration_count < kMaxIterationForPageGranularityMovement; p = next) {
    ++iteration_count;

    if (direction == SelectionModifyVerticalDirection::kUp) {
      next = CreateVisiblePosition(
          PreviousLinePosition(p.ToPositionWithAffinity(), x_pos));
    } else {
      next = CreateVisiblePosition(
          NextLinePosition(p.ToPositionWithAffinity(), x_pos));
    }

    if (next.IsNull() || next.DeepEquivalent() == p.DeepEquivalent())
      break;
    int next_y;
    DCHECK(next.IsValid()) << next;
    if (!AbsoluteCaretY(next.ToPositionWithAffinity(), next_y))
      break;
    if (direction == SelectionModifyVerticalDirection::kUp)
      next_y = -next_y;
    if (next_y - start_y > static_cast<int>(vertical_distance))
      break;
    if (next_y >= last_y) {
      last_y = next_y;
      result = next;
    }
  }

  if (result.IsNull())
    return false;

  switch (alter) {
    case SelectionModifyAlteration::kMove:
      current_selection_ =
          SelectionInFlatTree::Builder()
              .Collapse(result.ToPositionWithAffinity())
              .SetAffinity(direction == SelectionModifyVerticalDirection::kUp
                               ? TextAffinity::kUpstream
                               : TextAffinity::kDownstream)
              .Build();
      break;
    case SelectionModifyAlteration::kExtend: {
      current_selection_ = SelectionInFlatTree::Builder()
                               .Collapse(selection_.Base())
                               .Extend(result.DeepEquivalent())
                               .Build();
      break;
    }
  }

  return true;
}

// Abs x/y position of the caret ignoring transforms.
// TODO(yosin) navigation with transforms should be smarter.
static LayoutUnit LineDirectionPointForBlockDirectionNavigationOf(
    const VisiblePositionInFlatTree& visible_position) {
  if (visible_position.IsNull())
    return LayoutUnit();

  const LocalCaretRect& caret_rect =
      LocalCaretRectOfPosition(visible_position.ToPositionWithAffinity());
  if (caret_rect.IsEmpty())
    return LayoutUnit();

  // This ignores transforms on purpose, for now. Vertical navigation is done
  // without consulting transforms, so that 'up' in transformed text is 'up'
  // relative to the text, not absolute 'up'.
  PhysicalOffset caret_point =
      UNLIKELY(caret_rect.layout_object->HasFlippedBlocksWritingMode())
          ? caret_rect.rect.MaxXMinYCorner()
          : caret_rect.rect.MinXMinYCorner();
  caret_point = caret_rect.layout_object->LocalToAbsolutePoint(
      caret_point, kIgnoreTransforms);
  return caret_rect.layout_object->IsHorizontalWritingMode() ? caret_point.left
                                                             : caret_point.top;
}

LayoutUnit SelectionModifier::LineDirectionPointForBlockDirectionNavigation(
    const PositionInFlatTree& pos) {
  LayoutUnit x;

  if (selection_.IsNone())
    return x;

  if (x_pos_for_vertical_arrow_navigation_ ==
      NoXPosForVerticalArrowNavigation()) {
    VisiblePositionInFlatTree visible_position =
        CreateVisiblePosition(pos, selection_.Affinity());
    // VisiblePositionInFlatTree creation can fail here if a node containing the
    // selection becomes visibility:hidden after the selection is created and
    // before this function is called.
    x = LineDirectionPointForBlockDirectionNavigationOf(visible_position);
    x_pos_for_vertical_arrow_navigation_ = x;
  } else {
    x = x_pos_for_vertical_arrow_navigation_;
  }

  return x;
}

}  // namespace blink
