/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
 * reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

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

#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.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/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"

namespace blink {

namespace {

// TODO(yoichio): Share condition between NGOffsetMapping::AcceptsPosition.
bool ShouldUseLayoutNGTextContent(const Node& node) {
  LayoutObject* layout_object = node.GetLayoutObject();
  DCHECK(layout_object);
  if (layout_object->IsInline())
    return layout_object->ContainingNGBlockFlow();
  if (auto* block_flow = DynamicTo<LayoutBlockFlow>(layout_object))
    return NGBlockNode::CanUseNewLayout(*block_flow);
  return false;
}

}  // namespace

// The current selection to be painted is represented as 2 pairs of
// (Node, offset).
// Each offset represents text offsets on selection edge if it is text.
// For example, suppose we select "f^oo<br><img>|",
// |start_offset_| is 1 and |end_offset_| is nullopt.
// If on NG, offset is on text content offset rather than each text node.
class SelectionPaintRange : public GarbageCollected<SelectionPaintRange> {
 public:
  SelectionPaintRange() = default;
  SelectionPaintRange(const Node& passed_start_node,
                      base::Optional<unsigned> passed_start_offset,
                      const Node& passed_end_node,
                      base::Optional<unsigned> passed_end_offset)
      : start_node(passed_start_node),
        start_offset(passed_start_offset),
        end_node(passed_end_node),
        end_offset(passed_end_offset) {}
  void Trace(Visitor* visitor) {
    visitor->Trace(start_node);
    visitor->Trace(end_node);
  }

  bool IsNull() const { return !start_node; }
  void AssertSanity() const {
#if DCHECK_IS_ON()
    if (start_node) {
      DCHECK(end_node);
      DCHECK(start_node->GetLayoutObject()->GetSelectionState() ==
                 SelectionState::kStart ||
             start_node->GetLayoutObject()->GetSelectionState() ==
                 SelectionState::kStartAndEnd);
      DCHECK(end_node->GetLayoutObject()->GetSelectionState() ==
                 SelectionState::kEnd ||
             end_node->GetLayoutObject()->GetSelectionState() ==
                 SelectionState::kStartAndEnd);
      return;
    }
    DCHECK(!end_node);
    DCHECK(!start_offset.has_value());
    DCHECK(!end_offset.has_value());
#endif
  }

  Member<const Node> start_node;
  base::Optional<unsigned> start_offset;
  Member<const Node> end_node;
  base::Optional<unsigned> end_offset;
};

LayoutSelection::LayoutSelection(FrameSelection& frame_selection)
    : frame_selection_(&frame_selection),
      has_pending_selection_(false),
      paint_range_(MakeGarbageCollected<SelectionPaintRange>()) {}

enum class SelectionMode {
  kNone,
  kRange,
  kBlockCursor,
};

void LayoutSelection::AssertIsValid() const {
  const Document& document = frame_selection_->GetDocument();
  DCHECK_GE(document.Lifecycle().GetState(), DocumentLifecycle::kLayoutClean);
  DCHECK(!document.IsSlotAssignmentOrLegacyDistributionDirty());
  DCHECK(!has_pending_selection_);
}

static SelectionMode ComputeSelectionMode(
    const FrameSelection& frame_selection) {
  const SelectionInDOMTree& selection_in_dom =
      frame_selection.GetSelectionInDOMTree();
  if (selection_in_dom.IsRange())
    return SelectionMode::kRange;
  DCHECK(selection_in_dom.IsCaret());
  if (!frame_selection.ShouldShowBlockCursor())
    return SelectionMode::kNone;
  if (IsLogicalEndOfLine(CreateVisiblePosition(selection_in_dom.Base())))
    return SelectionMode::kNone;
  return SelectionMode::kBlockCursor;
}

static EphemeralRangeInFlatTree CalcSelectionInFlatTree(
    const FrameSelection& frame_selection) {
  const SelectionInDOMTree& selection_in_dom =
      frame_selection.GetSelectionInDOMTree();
  switch (ComputeSelectionMode(frame_selection)) {
    case SelectionMode::kNone:
      return {};
    case SelectionMode::kRange: {
      const PositionInFlatTree& base =
          ToPositionInFlatTree(selection_in_dom.Base());
      const PositionInFlatTree& extent =
          ToPositionInFlatTree(selection_in_dom.Extent());
      if (base.IsNull() || extent.IsNull() || base == extent ||
          !base.IsValidFor(frame_selection.GetDocument()) ||
          !extent.IsValidFor(frame_selection.GetDocument()))
        return {};
      return base <= extent ? EphemeralRangeInFlatTree(base, extent)
                            : EphemeralRangeInFlatTree(extent, base);
    }
    case SelectionMode::kBlockCursor: {
      const PositionInFlatTree& base =
          CreateVisiblePosition(ToPositionInFlatTree(selection_in_dom.Base()))
              .DeepEquivalent();
      if (base.IsNull())
        return {};
      const PositionInFlatTree end_position =
          NextPositionOf(base, PositionMoveType::kGraphemeCluster);
      if (end_position.IsNull())
        return {};
      return base <= end_position
                 ? EphemeralRangeInFlatTree(base, end_position)
                 : EphemeralRangeInFlatTree(end_position, base);
    }
  }
  NOTREACHED();
  return {};
}

// OldSelectedNodes is current selected Nodes with
// current SelectionState which is kStart, kEnd, kStartAndEnd or kInside.
struct OldSelectedNodes {
  STACK_ALLOCATED();

 public:
  OldSelectedNodes()
      : paint_range(MakeGarbageCollected<SelectionPaintRange>()) {}
  OldSelectedNodes(OldSelectedNodes&& other) {
    paint_range = other.paint_range;
    selected_map = std::move(other.selected_map);
  }

  SelectionPaintRange* paint_range;
  HeapHashMap<Member<const Node>, SelectionState> selected_map;

 private:
  DISALLOW_COPY_AND_ASSIGN(OldSelectedNodes);
};

std::ostream& operator<<(std::ostream&, const OldSelectedNodes&);

// This struct represents a selection range in layout tree and each
// Node is SelectionState-marked.
struct NewPaintRangeAndSelectedNodes {
  STACK_ALLOCATED();

 public:
  NewPaintRangeAndSelectedNodes()
      : paint_range(MakeGarbageCollected<SelectionPaintRange>()) {}
  NewPaintRangeAndSelectedNodes(
      SelectionPaintRange* passed_paint_range,
      HeapHashSet<Member<const Node>>&& passed_selected_objects)
      : paint_range(passed_paint_range),
        selected_objects(std::move(passed_selected_objects)) {}
  NewPaintRangeAndSelectedNodes(NewPaintRangeAndSelectedNodes&& other) {
    paint_range = other.paint_range;
    selected_objects = std::move(other.selected_objects);
  }

  void AssertSanity() const {
#if DCHECK_IS_ON()
    paint_range->AssertSanity();
    if (paint_range->start_node) {
      DCHECK(selected_objects.Contains(paint_range->start_node)) << this;
      DCHECK(selected_objects.Contains(paint_range->end_node)) << this;
      return;
    }
    DCHECK(selected_objects.IsEmpty()) << this;
#endif
  }

  SelectionPaintRange* paint_range;
  HeapHashSet<Member<const Node>> selected_objects;

 private:
  DISALLOW_COPY_AND_ASSIGN(NewPaintRangeAndSelectedNodes);
};

std::ostream& operator<<(std::ostream&, const NewPaintRangeAndSelectedNodes&);

static void SetShouldInvalidateIfNeeded(LayoutObject* layout_object) {
  if (layout_object->ShouldInvalidateSelection())
    return;
  layout_object->SetShouldInvalidateSelection();

  // We should invalidate if ancestor of |layout_object| is LayoutSVGText
  // because SVGRootInlineBoxPainter::Paint() paints selection for
  // |layout_object| in/ LayoutSVGText and it is invoked when parent
  // LayoutSVGText is invalidated.
  // That is different from InlineTextBoxPainter::Paint() which paints
  // LayoutText selection when LayoutText is invalidated.
  if (!layout_object->IsSVG())
    return;
  for (LayoutObject* parent = layout_object->Parent(); parent;
       parent = parent->Parent()) {
    if (parent->IsSVGRoot())
      return;
    if (parent->IsSVGText()) {
      if (!parent->ShouldInvalidateSelection())
        parent->SetShouldInvalidateSelection();
      return;
    }
  }
}

static LayoutTextFragment* FirstLetterPartFor(
    const LayoutObject* layout_object) {
  // TODO(yoichio): LayoutText::GetFirstLetterPart() should be typed
  // LayoutTextFragment.
  if (const LayoutText* layout_text = ToLayoutTextOrNull(layout_object))
    return ToLayoutTextFragment(layout_text->GetFirstLetterPart());
  return nullptr;
}

static void SetShouldInvalidateIfNeeded(const Node& node) {
  LayoutObject* layout_object = node.GetLayoutObject();
  if (!layout_object)
    return;
  if (LayoutTextFragment* first_letter = FirstLetterPartFor(layout_object))
    SetShouldInvalidateIfNeeded(first_letter);
  SetShouldInvalidateIfNeeded(layout_object);
}

static void SetSelectionStateIfNeeded(const Node& node, SelectionState state) {
  DCHECK_NE(state, SelectionState::kContain) << node;
  DCHECK_NE(state, SelectionState::kNone) << node;
  LayoutObject* layout_object = node.GetLayoutObject();
  if (layout_object->GetSelectionState() == state)
    return;
  layout_object->SetSelectionState(state);

  // Set ancestors SelectionState kContain for CSS ::selection style.
  // See LayoutObject::InvalidateSelectedChildrenOnStyleChange().
  for (Node& ancestor : FlatTreeTraversal::AncestorsOf(node)) {
    LayoutObject* ancestor_layout = ancestor.GetLayoutObject();
    if (!ancestor_layout)
      continue;
    if (ancestor_layout->GetSelectionState() == SelectionState::kContain)
      return;
    ancestor_layout->LayoutObject::SetSelectionState(SelectionState::kContain);
  }
}

// Set ShouldInvalidateSelection flag of LayoutObjects
// comparing them in |new_range| and |old_range|.
static void SetShouldInvalidateSelection(
    const NewPaintRangeAndSelectedNodes& new_range,
    const OldSelectedNodes& old_selected_objects) {
  // We invalidate each LayoutObject in
  // MakeGarbageCollected<SelectionPaintRange> which has SelectionState of
  // kStart, kEnd, kStartAndEnd, or kInside and is not in old
  // SelectionPaintRange.
  for (const Node* node : new_range.selected_objects) {
    if (old_selected_objects.selected_map.Contains(node))
      continue;
    const SelectionState new_state =
        node->GetLayoutObject()->GetSelectionState();
    DCHECK_NE(new_state, SelectionState::kContain) << node;
    DCHECK_NE(new_state, SelectionState::kNone) << node;
    SetShouldInvalidateIfNeeded(*node);
  }
  // For LayoutObject in old SelectionPaintRange, we invalidate LayoutObjects
  // each of:
  // 1. LayoutObject was painted and would not be painted.
  // 2. LayoutObject was not painted and would be painted.
  for (const auto& key_value : old_selected_objects.selected_map) {
    const Node* const node = key_value.key;
    const SelectionState old_state = key_value.value;
    const SelectionState new_state =
        node->GetLayoutObject()->GetSelectionState();
    if (new_state == old_state)
      continue;
    DCHECK(new_state != SelectionState::kNone ||
           old_state != SelectionState::kNone)
        << node;
    DCHECK_NE(new_state, SelectionState::kContain) << node;
    DCHECK_NE(old_state, SelectionState::kContain) << node;
    SetShouldInvalidateIfNeeded(*node);
  }

  // Invalidate Selection start/end is moving on a same node.
  const SelectionPaintRange& new_paint_range = *new_range.paint_range;
  const SelectionPaintRange& old_paint_range =
      *old_selected_objects.paint_range;
  if (new_paint_range.IsNull())
    return;
  if (new_paint_range.start_node->IsTextNode() &&
      new_paint_range.start_node == old_paint_range.start_node &&
      new_paint_range.start_offset != old_paint_range.start_offset)
    SetShouldInvalidateIfNeeded(*new_paint_range.start_node);
  if (new_paint_range.end_node->IsTextNode() &&
      new_paint_range.end_node == old_paint_range.end_node &&
      new_paint_range.end_offset != old_paint_range.end_offset)
    SetShouldInvalidateIfNeeded(*new_paint_range.end_node);
}

static bool IsDisplayContentElement(const Node& node) {
  if (!node.IsElementNode())
    return false;
  const ComputedStyle* const style = node.GetComputedStyle();
  return style && style->Display() == EDisplay::kContents;
}

template <typename Visitor>
static void VisitSelectedInclusiveDescendantsOfInternal(const Node& node,
                                                        Visitor* visitor) {
  // Display:content element appears in a flat tree even it doesn't have
  // a LayoutObject but we need to visit its children.
  if (!IsDisplayContentElement(node)) {
    LayoutObject* layout_object = node.GetLayoutObject();
    if (!layout_object)
      return;
    if (layout_object->GetSelectionState() == SelectionState::kNone)
      return;
    visitor->Visit(node);
  }

  for (Node& child : FlatTreeTraversal::ChildrenOf(node))
    VisitSelectedInclusiveDescendantsOfInternal(child, visitor);
}

static inline bool IsFlatTreeClean(const Node& node) {
  return !node.GetDocument().IsSlotAssignmentOrLegacyDistributionDirty();
}

template <typename Visitor>
static void VisitSelectedInclusiveDescendantsOf(const Node& node,
                                                Visitor* visitor) {
  DCHECK(IsFlatTreeClean(node));
  return VisitSelectedInclusiveDescendantsOfInternal(node, visitor);
}

static OldSelectedNodes ResetOldSelectedNodes(
    const Node& root,
    base::Optional<unsigned> old_start_offset,
    base::Optional<unsigned> old_end_offset) {
  class OldSelectedVisitor {
    STACK_ALLOCATED();

   public:
    OldSelectedVisitor(base::Optional<unsigned> passed_old_start_offset,
                       base::Optional<unsigned> passed_old_end_offset)
        : old_start_offset(passed_old_start_offset),
          old_end_offset(passed_old_end_offset) {}

    void Visit(const Node& node) {
      LayoutObject* layout_object = node.GetLayoutObject();
      const SelectionState old_state = layout_object->GetSelectionState();
      DCHECK_NE(old_state, SelectionState::kNone) << node;
      layout_object->SetSelectionState(SelectionState::kNone);
      if (old_state == SelectionState::kContain)
        return;
      old_selected_objects.selected_map.insert(&node, old_state);
      if (old_state == SelectionState::kInside)
        return;
      switch (old_state) {
        case SelectionState::kStart: {
          DCHECK(!old_selected_objects.paint_range->start_node);
          old_selected_objects.paint_range->start_node = node;
          old_selected_objects.paint_range->start_offset = old_start_offset;
          break;
        }
        case SelectionState::kEnd: {
          DCHECK(!old_selected_objects.paint_range->end_node);
          old_selected_objects.paint_range->end_node = node;
          old_selected_objects.paint_range->end_offset = old_end_offset;
          break;
        }
        case SelectionState::kStartAndEnd: {
          DCHECK(!old_selected_objects.paint_range->start_node);
          DCHECK(!old_selected_objects.paint_range->end_node);
          old_selected_objects.paint_range->start_node = node;
          old_selected_objects.paint_range->start_offset = old_start_offset;
          old_selected_objects.paint_range->end_node = node;
          old_selected_objects.paint_range->end_offset = old_end_offset;
          break;
        }
        default: {
          NOTREACHED();
          break;
        }
      }
    }

    OldSelectedNodes old_selected_objects;
    const base::Optional<unsigned> old_start_offset;
    const base::Optional<unsigned> old_end_offset;
  } visitor(old_start_offset, old_end_offset);
  VisitSelectedInclusiveDescendantsOf(root, &visitor);
  return std::move(visitor.old_selected_objects);
}

static base::Optional<unsigned> ComputeStartOffset(
    const Node& node,
    const PositionInFlatTree& selection_start) {
  if (!node.IsTextNode())
    return base::nullopt;

  if (&node == selection_start.AnchorNode())
    return selection_start.OffsetInContainerNode();
  return 0;
}

static base::Optional<unsigned> ComputeEndOffset(
    const Node& node,
    const PositionInFlatTree& selection_end) {
  auto* text_node = DynamicTo<Text>(node);
  if (!text_node)
    return base::nullopt;

  if (&node == selection_end.AnchorNode())
    return selection_end.OffsetInContainerNode();
  return text_node->length();
}

#if DCHECK_IS_ON()
// Position should be offset on text or before/after a break element.
static bool IsPositionValidText(const Position& position) {
  if (position.AnchorNode()->IsTextNode() && position.IsOffsetInAnchor())
    return true;
  if ((IsA<HTMLBRElement>(position.AnchorNode()) ||
       IsA<HTMLWBRElement>(position.AnchorNode())) &&
      (position.IsBeforeAnchor() || position.IsAfterAnchor()))
    return true;
  return false;
}
#endif

static base::Optional<unsigned> GetTextContentOffset(const Position& position) {
  if (position.IsNull())
    return base::nullopt;
#if DCHECK_IS_ON()
  DCHECK(IsPositionValidText(position));
#endif
  DCHECK(ShouldUseLayoutNGTextContent(*position.AnchorNode()));
  const NGOffsetMapping* const offset_mapping =
      NGOffsetMapping::GetFor(position);
  DCHECK(offset_mapping);
  const base::Optional<unsigned>& ng_offset =
      offset_mapping->GetTextContentOffset(position);
  return ng_offset;
}

// Computes text content offset of selection start if |layout_object| is
// LayoutText.
static base::Optional<unsigned> GetTextContentOffsetStart(
    const Node& node,
    base::Optional<unsigned> node_offset) {
  if (!node.GetLayoutObject()->IsText())
    return base::nullopt;
  if (node.IsTextNode()) {
    DCHECK(node_offset.has_value()) << node;
    return GetTextContentOffset(Position(node, node_offset.value()));
  }

  DCHECK(IsA<HTMLWBRElement>(node) || IsA<HTMLBRElement>(node)) << node;
  DCHECK(!node_offset.has_value()) << node;
  return GetTextContentOffset(Position::BeforeNode(node));
}

// Computes text content offset of selection end if |layout_object| is
// LayoutText.
static base::Optional<unsigned> GetTextContentOffsetEnd(
    const Node& node,
    base::Optional<unsigned> node_offset) {
  if (!node.GetLayoutObject()->IsText())
    return {};
  if (node.IsTextNode()) {
    DCHECK(node_offset.has_value()) << node;
    return GetTextContentOffset(Position(node, node_offset.value()));
  }

  DCHECK(IsA<HTMLWBRElement>(node) || IsA<HTMLBRElement>(node)) << node;
  DCHECK(!node_offset.has_value()) << node;
  return GetTextContentOffset(Position::AfterNode(node));
}

static SelectionPaintRange* ComputeNewPaintRange(
    const SelectionPaintRange& paint_range) {
  DCHECK(!paint_range.IsNull());

  const Node& start_node = *paint_range.start_node;
  // If LayoutObject is not in NG, use legacy offset.
  const base::Optional<unsigned> start_offset =
      ShouldUseLayoutNGTextContent(start_node)
          ? GetTextContentOffsetStart(start_node, paint_range.start_offset)
          : paint_range.start_offset;

  const Node& end_node = *paint_range.end_node;
  const base::Optional<unsigned> end_offset =
      ShouldUseLayoutNGTextContent(end_node)
          ? GetTextContentOffsetEnd(end_node, paint_range.end_offset)
          : paint_range.end_offset;

  return MakeGarbageCollected<SelectionPaintRange>(
      *paint_range.start_node, start_offset, *paint_range.end_node, end_offset);
}

static unsigned ClampOffset(unsigned offset,
                            unsigned start_offset,
                            unsigned end_offset) {
  DCHECK_LE(start_offset, end_offset);
  return std::min(std::max(offset, start_offset), end_offset);
}

static Text* AssociatedTextNode(const LayoutText& text) {
  if (const LayoutTextFragment* fragment = ToLayoutTextFragmentOrNull(text))
    return fragment->AssociatedTextNode();
  if (Node* node = text.GetNode())
    return DynamicTo<Text>(node);
  return nullptr;
}

static SelectionState GetSelectionStateFor(const LayoutText& layout_text) {
  if (const LayoutTextFragment* text_fragment =
          ToLayoutTextFragmentOrNull(layout_text)) {
    Node* node = text_fragment->AssociatedTextNode();
    if (!node)
      return SelectionState::kNone;
    return node->GetLayoutObject()->GetSelectionState();
  }
  return layout_text.GetSelectionState();
}

static SelectionState GetSelectionStateFor(const NGInlineCursor& cursor) {
  DCHECK(cursor.Current().GetLayoutObject() &&
         cursor.Current().GetLayoutObject()->IsText());
  return GetSelectionStateFor(
      ToLayoutText(*cursor.Current().GetLayoutObject()));
}

bool LayoutSelection::IsSelected(const LayoutObject& layout_object) {
  if (const LayoutText* layout_text = ToLayoutTextOrNull(layout_object))
    return GetSelectionStateFor(*layout_text) != SelectionState::kNone;
  return layout_object.GetSelectionState() != SelectionState::kNone;
}

static inline unsigned ClampOffset(unsigned node_offset,
                                   const LayoutTextFragment& fragment) {
  if (fragment.Start() > node_offset)
    return 0;
  return std::min(node_offset - fragment.Start(), fragment.FragmentLength());
}

static LayoutTextSelectionStatus ComputeSelectionStatusForNode(
    const Text& text,
    SelectionState selection_state,
    base::Optional<unsigned> start_offset,
    base::Optional<unsigned> end_offset) {
  switch (selection_state) {
    case SelectionState::kInside:
      return {0, text.length(), SelectionIncludeEnd::kInclude};
    case SelectionState::kStart:
      return {start_offset.value(), text.length(),
              SelectionIncludeEnd::kInclude};
    case SelectionState::kEnd:
      return {0, end_offset.value(), SelectionIncludeEnd::kNotInclude};
    case SelectionState::kStartAndEnd:
      return {start_offset.value(), end_offset.value(),
              SelectionIncludeEnd::kNotInclude};
    default:
      NOTREACHED();
      return {0, 0, SelectionIncludeEnd::kNotInclude};
  }
}

LayoutTextSelectionStatus LayoutSelection::ComputeSelectionStatus(
    const LayoutText& layout_text) const {
  AssertIsValid();
  const SelectionState selection_state = GetSelectionStateFor(layout_text);
  if (selection_state == SelectionState::kNone)
    return {0, 0, SelectionIncludeEnd::kNotInclude};
  if (Text* text = AssociatedTextNode(layout_text)) {
    const LayoutTextSelectionStatus text_status = ComputeSelectionStatusForNode(
        *text, selection_state, paint_range_->start_offset,
        paint_range_->end_offset);
    if (const LayoutTextFragment* text_fragment =
            ToLayoutTextFragmentOrNull(layout_text)) {
      return {ClampOffset(text_status.start, *text_fragment),
              ClampOffset(text_status.end, *text_fragment),
              text_status.include_end};
    }
    return text_status;
  }
  // TODO(yoichio): This is really weird legacy behavior. Remove this.
  if (layout_text.IsBR() && selection_state == SelectionState::kEnd)
    return {0, 0, SelectionIncludeEnd::kNotInclude};
  return {0, layout_text.TextLength(), SelectionIncludeEnd::kInclude};
}

LayoutTextSelectionStatus FrameSelection::ComputeLayoutSelectionStatus(
    const LayoutText& text) const {
  return layout_selection_->ComputeSelectionStatus(text);
}

// FrameSelection holds selection offsets in layout block flow at
// LayoutSelection::Commit() if selection starts/ends within Text that
// each LayoutObject::SelectionState indicates.
// These offset can be out of fragment because SelectionState is of each
// LayoutText and not of each fragment for it.
LayoutSelectionStatus LayoutSelection::ComputeSelectionStatus(
    const NGInlineCursor& cursor) const {
  // We don't paint selection on ellipsis.
  if (cursor.Current().IsEllipsis())
    return {0, 0, SelectSoftLineBreak::kNotSelected};
  const NGTextOffset offset = cursor.Current().TextOffset();
  const unsigned start_offset = offset.start;
  const unsigned end_offset = offset.end;
  switch (GetSelectionStateFor(cursor)) {
    case SelectionState::kStart: {
      const unsigned start_in_block = paint_range_->start_offset.value();
      const bool is_continuous = start_in_block <= end_offset;
      return {ClampOffset(start_in_block, start_offset, end_offset), end_offset,
              (is_continuous && cursor.IsBeforeSoftLineBreak())
                  ? SelectSoftLineBreak::kSelected
                  : SelectSoftLineBreak::kNotSelected};
    }
    case SelectionState::kEnd: {
      const unsigned end_in_block = paint_range_->end_offset.value();
      const unsigned end_in_fragment =
          ClampOffset(end_in_block, start_offset, end_offset);
      const bool is_continuous = end_offset < end_in_block;
      return {start_offset, end_in_fragment,
              (is_continuous && cursor.IsBeforeSoftLineBreak())
                  ? SelectSoftLineBreak::kSelected
                  : SelectSoftLineBreak::kNotSelected};
    }
    case SelectionState::kStartAndEnd: {
      const unsigned start_in_block = paint_range_->start_offset.value();
      const unsigned end_in_block = paint_range_->end_offset.value();
      const unsigned end_in_fragment =
          ClampOffset(end_in_block, start_offset, end_offset);
      const bool is_continuous =
          start_in_block <= end_offset && end_offset < end_in_block;
      return {ClampOffset(start_in_block, start_offset, end_offset),
              end_in_fragment,
              (is_continuous && cursor.IsBeforeSoftLineBreak())
                  ? SelectSoftLineBreak::kSelected
                  : SelectSoftLineBreak::kNotSelected};
    }
    case SelectionState::kInside: {
      return {start_offset, end_offset,
              cursor.IsBeforeSoftLineBreak()
                  ? SelectSoftLineBreak::kSelected
                  : SelectSoftLineBreak::kNotSelected};
    }
    default:
      // This block is not included in selection.
      return {0, 0, SelectSoftLineBreak::kNotSelected};
  }
}

static NewPaintRangeAndSelectedNodes CalcSelectionRangeAndSetSelectionState(
    const FrameSelection& frame_selection) {
  const SelectionInDOMTree& selection_in_dom =
      frame_selection.GetSelectionInDOMTree();
  if (selection_in_dom.IsNone())
    return {};

  const EphemeralRangeInFlatTree& selection =
      CalcSelectionInFlatTree(frame_selection);
  if (selection.IsCollapsed() || frame_selection.IsHidden())
    return {};

  // Find first/last Node which has a visible LayoutObject while
  // marking SelectionState and collecting invalidation candidate LayoutObjects.
  const Node* start_node = nullptr;
  const Node* end_node = nullptr;
  HeapHashSet<Member<const Node>> selected_objects;
  for (Node& node : selection.Nodes()) {
    LayoutObject* const layout_object = node.GetLayoutObject();
    if (!layout_object || !layout_object->CanBeSelectionLeaf())
      continue;

    if (!start_node) {
      DCHECK(!end_node);
      start_node = end_node = &node;
      continue;
    }

    // In this loop, |end_node| is pointing current last candidate
    // LayoutObject and if it is not start and we find next, we mark the
    // current one as kInside.
    if (end_node != start_node) {
      SetSelectionStateIfNeeded(*end_node, SelectionState::kInside);
      selected_objects.insert(end_node);
    }
    end_node = &node;
  }

  // No valid LayOutObject found.
  if (!start_node) {
    DCHECK(!end_node);
    return {};
  }

  // Compute offset. It has value iff start/end is text.
  const base::Optional<unsigned> start_offset = ComputeStartOffset(
      *start_node, selection.StartPosition().ToOffsetInAnchor());
  const base::Optional<unsigned> end_offset =
      ComputeEndOffset(*end_node, selection.EndPosition().ToOffsetInAnchor());
  if (start_node == end_node) {
    SetSelectionStateIfNeeded(*start_node, SelectionState::kStartAndEnd);
    selected_objects.insert(start_node);
  } else {
    SetSelectionStateIfNeeded(*start_node, SelectionState::kStart);
    selected_objects.insert(start_node);
    SetSelectionStateIfNeeded(*end_node, SelectionState::kEnd);
    selected_objects.insert(end_node);
  }

  SelectionPaintRange* new_range = MakeGarbageCollected<SelectionPaintRange>(
      *start_node, start_offset, *end_node, end_offset);
  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
    return {new_range, std::move(selected_objects)};
  return {ComputeNewPaintRange(*new_range), std::move(selected_objects)};
}

void LayoutSelection::SetHasPendingSelection() {
  has_pending_selection_ = true;
}

void LayoutSelection::Commit() {
  if (!has_pending_selection_)
    return;
  has_pending_selection_ = false;

  DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate());
  DCHECK_GE(frame_selection_->GetDocument().Lifecycle().GetState(),
            DocumentLifecycle::kLayoutClean);
  DocumentLifecycle::DisallowTransitionScope disallow_transition(
      frame_selection_->GetDocument().Lifecycle());

  const OldSelectedNodes& old_selected_objects = ResetOldSelectedNodes(
      frame_selection_->GetDocument(), paint_range_->start_offset,
      paint_range_->end_offset);
  const NewPaintRangeAndSelectedNodes& new_range =
      CalcSelectionRangeAndSetSelectionState(*frame_selection_);
  new_range.AssertSanity();
  DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView());
  SetShouldInvalidateSelection(new_range, old_selected_objects);

  paint_range_ = new_range.paint_range;
}

void LayoutSelection::ContextDestroyed() {
  has_pending_selection_ = false;
  paint_range_->start_node = nullptr;
  paint_range_->start_offset = base::nullopt;
  paint_range_->end_node = nullptr;
  paint_range_->end_offset = base::nullopt;
}

static PhysicalRect SelectionRectForLayoutObject(const LayoutObject* object) {
  if (!object->IsRooted())
    return PhysicalRect();

  if (!object->CanUpdateSelectionOnRootLineBoxes())
    return PhysicalRect();

  return object->AbsoluteSelectionRect();
}

template <typename Visitor>
static void VisitLayoutObjectsOf(const Node& node, Visitor* visitor) {
  LayoutObject* layout_object = node.GetLayoutObject();
  if (!layout_object)
    return;
  if (layout_object->GetSelectionState() == SelectionState::kContain)
    return;
  if (LayoutTextFragment* first_letter = FirstLetterPartFor(layout_object))
    visitor->Visit(first_letter);
  visitor->Visit(layout_object);
}

IntRect LayoutSelection::AbsoluteSelectionBounds() {
  Commit();
  if (paint_range_->IsNull())
    return IntRect();

  // Create a single bounding box rect that encloses the whole selection.
  class SelectionBoundsVisitor {
    STACK_ALLOCATED();

   public:
    void Visit(const Node& node) { VisitLayoutObjectsOf(node, this); }
    void Visit(LayoutObject* layout_object) {
      selected_rect.Unite(SelectionRectForLayoutObject(layout_object));
    }
    PhysicalRect selected_rect;
  } visitor;
  VisitSelectedInclusiveDescendantsOf(frame_selection_->GetDocument(),
                                      &visitor);
  return PixelSnappedIntRect(visitor.selected_rect);
}

void LayoutSelection::InvalidatePaintForSelection() {
  if (paint_range_->IsNull())
    return;

  class InvalidatingVisitor {
    STACK_ALLOCATED();

   public:
    void Visit(const Node& node) { VisitLayoutObjectsOf(node, this); }
    void Visit(LayoutObject* layout_object) {
      layout_object->SetShouldInvalidateSelection();
    }
  } visitor;
  VisitSelectedInclusiveDescendantsOf(frame_selection_->GetDocument(),
                                      &visitor);
}

void LayoutSelection::Trace(Visitor* visitor) {
  visitor->Trace(frame_selection_);
  visitor->Trace(paint_range_);
}

void PrintSelectionStatus(std::ostream& ostream, const Node& node) {
  ostream << (void*)&node;
  if (node.IsTextNode())
    ostream << "#text";
  else if (const auto* element = DynamicTo<Element>(node))
    ostream << element->tagName().Utf8();
  LayoutObject* layout_object = node.GetLayoutObject();
  if (!layout_object) {
    ostream << " <null LayoutObject>";
    return;
  }
  ostream << ' ' << layout_object->GetSelectionState();
}

#if DCHECK_IS_ON()
std::ostream& operator<<(std::ostream& ostream,
                         const base::Optional<unsigned>& offset) {
  if (offset.has_value())
    ostream << offset.value();
  else
    ostream << "<nullopt>";
  return ostream;
}

std::ostream& operator<<(std::ostream& ostream,
                         const SelectionPaintRange& range) {
  ostream << range.start_node << ": " << range.start_offset << ", "
          << range.end_node << ": " << range.end_offset;
  return ostream;
}

std::ostream& operator<<(
    std::ostream& ostream,
    const HeapHashMap<Member<const Node>, SelectionState>& map) {
  ostream << "[";
  const char* comma = "";
  for (const auto& key_value : map) {
    const Node* const node = key_value.key;
    const SelectionState old_state = key_value.value;
    ostream << comma << node << "." << old_state;
    comma = ", ";
  }
  ostream << "]";
  return ostream;
}

std::ostream& operator<<(std::ostream& ostream,
                         const OldSelectedNodes& old_node) {
  ostream << old_node.paint_range << ". " << old_node.selected_map;
  return ostream;
}

void PrintOldSelectedNodes(const OldSelectedNodes& old_node) {
  std::stringstream stream;
  stream << std::endl << old_node;
  LOG(INFO) << stream.str();
}

std::ostream& operator<<(
    std::ostream& ostream,
    const HeapHashSet<Member<const Node>>& selected_objects) {
  ostream << "[";
  const char* comma = "";
  for (const Node* node : selected_objects) {
    ostream << comma;
    PrintSelectionStatus(ostream, *node);
    comma = ", ";
  }
  ostream << "]";
  return ostream;
}

std::ostream& operator<<(std::ostream& ostream,
                         const NewPaintRangeAndSelectedNodes& new_range) {
  ostream << new_range.paint_range << ". " << new_range.selected_objects;
  return ostream;
}

void PrintSelectedNodes(const NewPaintRangeAndSelectedNodes& new_range) {
  std::stringstream stream;
  stream << std::endl << new_range;
  LOG(INFO) << stream.str();
}

void PrintSelectionStateInDocument(const FrameSelection& selection) {
  class PrintVisitor {
    STACK_ALLOCATED();

   public:
    void Visit(const Node& node) { PrintSelectionStatus(stream, node); }
    std::stringstream stream;
  } visitor;
  VisitSelectedInclusiveDescendantsOf(selection.GetDocument(), &visitor);
  LOG(INFO) << std::endl << visitor.stream.str();
}
#endif

}  // namespace blink
