/*
 * Copyright (C) 2004, 2005, 2006, 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 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/position.h"

#include <stdio.h>
#include <ostream>  // NOLINT
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/text_affinity.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

namespace blink {

#if DCHECK_IS_ON()
template <typename Strategy>
static bool CanBeAnchorNode(Node*);

template <>
bool CanBeAnchorNode<EditingStrategy>(Node* node) {
  return !node || !node->IsPseudoElement();
}

template <>
bool CanBeAnchorNode<EditingInFlatTreeStrategy>(Node* node) {
  return CanBeAnchorNode<EditingStrategy>(node) &&
         (!node || node->CanParticipateInFlatTree());
}
#endif

template <typename Strategy>
void PositionTemplate<Strategy>::Trace(Visitor* visitor) const {
  visitor->Trace(anchor_node_);
}

template <typename Strategy>
const TreeScope* PositionTemplate<Strategy>::CommonAncestorTreeScope(
    const PositionTemplate<Strategy>& a,
    const PositionTemplate<Strategy>& b) {
  if (!a.ComputeContainerNode() || !b.ComputeContainerNode())
    return nullptr;
  return a.ComputeContainerNode()->GetTreeScope().CommonAncestorTreeScope(
      b.ComputeContainerNode()->GetTreeScope());
}

template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::EditingPositionOf(
    const Node* anchor_node,
    int offset) {
  if (!anchor_node || anchor_node->IsTextNode())
    return PositionTemplate<Strategy>(anchor_node, offset);

  if (!EditingIgnoresContent(*anchor_node)) {
    return PositionTemplate<Strategy>::CreateWithoutValidationDeprecated(
        *anchor_node, offset);
  }

  if (offset == 0)
    return PositionTemplate<Strategy>(anchor_node,
                                      PositionAnchorType::kBeforeAnchor);

  // Note: |offset| can be >= 1, if |anchorNode| have child nodes, e.g.
  // using Node.appendChild() to add a child node TEXTAREA.
  DCHECK_GE(offset, 1);
  return PositionTemplate<Strategy>(anchor_node,
                                    PositionAnchorType::kAfterAnchor);
}

// TODO(editing-dev): Once we change type of |anchor_node_| to
// |Member<const Node>|, we should get rid of |const_cast<Node*>()|.
// See http://crbug.com/735327
template <typename Strategy>
PositionTemplate<Strategy>::PositionTemplate(const Node* anchor_node,
                                             PositionAnchorType anchor_type)
    : anchor_node_(const_cast<Node*>(anchor_node)),
      offset_(0),
      anchor_type_(anchor_type) {
#if DCHECK_IS_ON()
  DCHECK(anchor_node_);
  DCHECK_NE(anchor_type_, PositionAnchorType::kOffsetInAnchor);
  DCHECK(CanBeAnchorNode<Strategy>(anchor_node_.Get())) << anchor_node_;
  if (anchor_node_->IsTextNode()) {
    DCHECK(anchor_type_ == PositionAnchorType::kBeforeAnchor ||
           anchor_type_ == PositionAnchorType::kAfterAnchor)
        << *this;
    return;
  }
  if (!Strategy::Parent(*anchor_node_)) {
    // Before/After |anchor_node_| should have a parent node for converting
    // to offset in anchor position.
    DCHECK(IsBeforeChildren() || IsAfterChildren()) << *this;
    return;
  }
#endif
}

// TODO(editing-dev): Once we change type of |anchor_node_| to
// |Member<const Node>|, we should get rid of |const_cast<Node*>()|.
// See http://crbug.com/735327
template <typename Strategy>
PositionTemplate<Strategy>::PositionTemplate(const Node* anchor_node,
                                             int offset)
    : anchor_node_(const_cast<Node*>(anchor_node)),
      offset_(offset),
      anchor_type_(PositionAnchorType::kOffsetInAnchor) {
#if DCHECK_IS_ON()
  DCHECK(CanBeAnchorNode<Strategy>(anchor_node_.Get())) << anchor_node_;
  if (!anchor_node_) {
    DCHECK_EQ(offset, 0);
    return;
  }
  if (auto* data = DynamicTo<CharacterData>(anchor_node_.Get())) {
    DCHECK_GE(offset, 0);
    DCHECK_LE(static_cast<unsigned>(offset), data->length()) << anchor_node_;
    return;
  }
  DCHECK_GE(offset, 0);
  DCHECK_LE(static_cast<unsigned>(offset),
            Strategy::CountChildren(*anchor_node))
      << anchor_node_;
#endif
}

template <typename Strategy>
PositionTemplate<Strategy>::PositionTemplate(const Node& anchor_node,
                                             int offset)
    : PositionTemplate(&anchor_node, offset) {}

template <typename Strategy>
PositionTemplate<Strategy>::PositionTemplate(const PositionTemplate& other)
    : anchor_node_(other.anchor_node_),
      offset_(other.offset_),
      anchor_type_(other.anchor_type_) {}

// static
template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::CreateWithoutValidation(
    const Node& container,
    int offset) {
  PositionTemplate<Strategy> result(container, 0);
  result.offset_ = offset;
  return result;
}

// static
template <typename Strategy>
PositionTemplate<Strategy>
PositionTemplate<Strategy>::CreateWithoutValidationDeprecated(
    const Node& container,
    int offset) {
  return CreateWithoutValidation(container, offset);
}

// --

template <typename Strategy>
Node* PositionTemplate<Strategy>::ComputeContainerNode() const {
  if (!anchor_node_)
    return nullptr;

  switch (AnchorType()) {
    case PositionAnchorType::kAfterChildren:
    case PositionAnchorType::kOffsetInAnchor:
      return anchor_node_.Get();
    case PositionAnchorType::kBeforeAnchor:
    case PositionAnchorType::kAfterAnchor: {
      Node* const parent = Strategy::Parent(*anchor_node_);
      // TODO(https://crbug.com/889737), Once we fix the issue, we should have
      // |DCHECK(parent)|.
      return parent;
    }
  }
  NOTREACHED();
  return nullptr;
}

template <typename Strategy>
static int MinOffsetForNode(Node* anchor_node, int offset) {
  if (auto* data = DynamicTo<CharacterData>(anchor_node))
    return std::min(offset, static_cast<int>(data->length()));

  int new_offset = 0;
  for (Node* node = Strategy::FirstChild(*anchor_node);
       node && new_offset < offset; node = Strategy::NextSibling(*node))
    new_offset++;

  return new_offset;
}

template <typename Strategy>
int PositionTemplate<Strategy>::ComputeOffsetInContainerNode() const {
  if (!anchor_node_)
    return 0;

  switch (AnchorType()) {
    case PositionAnchorType::kAfterChildren:
      return LastOffsetInNode(*anchor_node_);
    case PositionAnchorType::kOffsetInAnchor:
      return MinOffsetForNode<Strategy>(anchor_node_.Get(), offset_);
    case PositionAnchorType::kBeforeAnchor:
      return Strategy::Index(*anchor_node_);
    case PositionAnchorType::kAfterAnchor:
      return Strategy::Index(*anchor_node_) + 1;
  }
  NOTREACHED();
  return 0;
}

// Neighbor-anchored positions are invalid DOM positions, so they need to be
// fixed up before handing them off to the Range object.
template <typename Strategy>
PositionTemplate<Strategy>
PositionTemplate<Strategy>::ParentAnchoredEquivalent() const {
  if (!anchor_node_)
    return PositionTemplate<Strategy>();

  // FIXME: This should only be necessary for legacy positions, but is also
  // needed for positions before and after Tables
  if (offset_ == 0 && !IsAfterAnchorOrAfterChildren()) {
    if (Strategy::Parent(*anchor_node_) &&
        (EditingIgnoresContent(*anchor_node_) ||
         IsDisplayInsideTable(anchor_node_.Get())))
      return InParentBeforeNode(*anchor_node_);
    return PositionTemplate<Strategy>(anchor_node_.Get(), 0);
  }
  if (!anchor_node_->IsCharacterDataNode() &&
      (IsAfterAnchorOrAfterChildren() ||
       static_cast<unsigned>(offset_) == anchor_node_->CountChildren()) &&
      (EditingIgnoresContent(*anchor_node_) ||
       IsDisplayInsideTable(anchor_node_.Get())) &&
      ComputeContainerNode()) {
    return InParentAfterNode(*anchor_node_);
  }

  return PositionTemplate<Strategy>(ComputeContainerNode(),
                                    ComputeOffsetInContainerNode());
}

template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::ToOffsetInAnchor()
    const {
  if (IsNull())
    return PositionTemplate<Strategy>();

  return PositionTemplate<Strategy>(ComputeContainerNode(),
                                    ComputeOffsetInContainerNode());
}

template <typename Strategy>
int PositionTemplate<Strategy>::ComputeEditingOffset() const {
  if (IsAfterAnchorOrAfterChildren())
    return Strategy::LastOffsetForEditing(anchor_node_.Get());
  return offset_;
}

template <typename Strategy>
Node* PositionTemplate<Strategy>::ComputeNodeBeforePosition() const {
  if (!anchor_node_)
    return nullptr;
  switch (AnchorType()) {
    case PositionAnchorType::kAfterChildren:
      return Strategy::LastChild(*anchor_node_);
    case PositionAnchorType::kOffsetInAnchor:
      return offset_ ? Strategy::ChildAt(*anchor_node_, offset_ - 1) : nullptr;
    case PositionAnchorType::kBeforeAnchor:
      return Strategy::PreviousSibling(*anchor_node_);
    case PositionAnchorType::kAfterAnchor:
      return anchor_node_.Get();
  }
  NOTREACHED();
  return nullptr;
}

template <typename Strategy>
Node* PositionTemplate<Strategy>::ComputeNodeAfterPosition() const {
  if (!anchor_node_)
    return nullptr;

  switch (AnchorType()) {
    case PositionAnchorType::kAfterChildren:
      return nullptr;
    case PositionAnchorType::kOffsetInAnchor:
      return Strategy::ChildAt(*anchor_node_, offset_);
    case PositionAnchorType::kBeforeAnchor:
      return anchor_node_.Get();
    case PositionAnchorType::kAfterAnchor:
      return Strategy::NextSibling(*anchor_node_);
  }
  NOTREACHED();
  return nullptr;
}

// An implementation of |Range::firstNode()|.
template <typename Strategy>
Node* PositionTemplate<Strategy>::NodeAsRangeFirstNode() const {
  if (!anchor_node_)
    return nullptr;
  if (!IsOffsetInAnchor())
    return ToOffsetInAnchor().NodeAsRangeFirstNode();
  if (anchor_node_->IsCharacterDataNode())
    return anchor_node_.Get();
  if (Node* child = Strategy::ChildAt(*anchor_node_, offset_))
    return child;
  if (!offset_)
    return anchor_node_.Get();
  return Strategy::NextSkippingChildren(*anchor_node_);
}

template <typename Strategy>
Node* PositionTemplate<Strategy>::NodeAsRangeLastNode() const {
  if (IsNull())
    return nullptr;
  if (Node* past_last_node = NodeAsRangePastLastNode())
    return Strategy::Previous(*past_last_node);
  return &Strategy::LastWithinOrSelf(*ComputeContainerNode());
}

// An implementation of |Range::pastLastNode()|.
template <typename Strategy>
Node* PositionTemplate<Strategy>::NodeAsRangePastLastNode() const {
  if (!anchor_node_)
    return nullptr;
  if (!IsOffsetInAnchor())
    return ToOffsetInAnchor().NodeAsRangePastLastNode();
  if (anchor_node_->IsCharacterDataNode())
    return Strategy::NextSkippingChildren(*anchor_node_);
  if (Node* child = Strategy::ChildAt(*anchor_node_, offset_))
    return child;
  return Strategy::NextSkippingChildren(*anchor_node_);
}

template <typename Strategy>
Node* PositionTemplate<Strategy>::CommonAncestorContainer(
    const PositionTemplate<Strategy>& other) const {
  return Strategy::CommonAncestor(*ComputeContainerNode(),
                                  *other.ComputeContainerNode());
}

static bool IsPositionConnected(const Position& position) {
  return position.AnchorNode() && position.AnchorNode()->isConnected();
}

static bool IsPositionConnected(const PositionInFlatTree& position) {
  if (position.IsNull())
    return false;
  return FlatTreeTraversal::Contains(*position.GetDocument(),
                                     *position.AnchorNode());
}

template <typename Strategy>
bool PositionTemplate<Strategy>::IsBeforeChildren() const {
  if (IsBeforeAnchor())
    return !Strategy::PreviousSibling(*anchor_node_);
  return IsOffsetInAnchor() && !offset_;
}

template <typename Strategy>
bool PositionTemplate<Strategy>::IsConnected() const {
  return IsPositionConnected(*this);
}

template <typename Strategy>
bool PositionTemplate<Strategy>::IsValidFor(const Document& document) const {
  if (IsNull())
    return true;
  if (GetDocument() != document)
    return false;
  if (!IsConnected())
    return false;
  return !IsOffsetInAnchor() ||
         OffsetInContainerNode() <= LastOffsetInNode(*AnchorNode());
}

int16_t ComparePositions(const PositionInFlatTree& position_a,
                         const PositionInFlatTree& position_b) {
  DCHECK(position_a.IsNotNull());
  DCHECK(position_b.IsNotNull());

  Node* container_a = position_a.ComputeContainerNode();
  Node* container_b = position_b.ComputeContainerNode();
  int offset_a = position_a.ComputeOffsetInContainerNode();
  int offset_b = position_b.ComputeOffsetInContainerNode();
  return ComparePositionsInFlatTree(container_a, offset_a, container_b,
                                    offset_b);
}

template <typename Strategy>
int16_t PositionTemplate<Strategy>::CompareTo(
    const PositionTemplate<Strategy>& other) const {
  return ComparePositions(*this, other);
}

template <typename Strategy>
bool PositionTemplate<Strategy>::operator<(
    const PositionTemplate<Strategy>& other) const {
  return ComparePositions(*this, other) < 0;
}

template <typename Strategy>
bool PositionTemplate<Strategy>::operator<=(
    const PositionTemplate<Strategy>& other) const {
  return ComparePositions(*this, other) <= 0;
}

template <typename Strategy>
bool PositionTemplate<Strategy>::operator>(
    const PositionTemplate<Strategy>& other) const {
  return ComparePositions(*this, other) > 0;
}

template <typename Strategy>
bool PositionTemplate<Strategy>::operator>=(
    const PositionTemplate<Strategy>& other) const {
  return ComparePositions(*this, other) >= 0;
}

template <typename Strategy>
bool PositionTemplate<Strategy>::IsEquivalent(
    const PositionTemplate<Strategy>& other) const {
  if (IsNull())
    return other.IsNull();
  if (anchor_type_ == other.anchor_type_)
    return *this == other;
  return ToOffsetInAnchor() == other.ToOffsetInAnchor();
}

template <typename Strategy>
bool PositionTemplate<Strategy>::AtFirstEditingPositionForNode() const {
  if (IsNull())
    return true;
  // FIXME: Position before anchor shouldn't be considered as at the first
  // editing position for node since that position resides outside of the node.
  switch (anchor_type_) {
    case PositionAnchorType::kOffsetInAnchor:
      return offset_ == 0;
    case PositionAnchorType::kBeforeAnchor:
      return true;
    case PositionAnchorType::kAfterChildren:
    case PositionAnchorType::kAfterAnchor:
      // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead
      // of DOM tree version.
      return !EditingStrategy::LastOffsetForEditing(AnchorNode());
  }
  NOTREACHED();
  return false;
}

template <typename Strategy>
bool PositionTemplate<Strategy>::AtLastEditingPositionForNode() const {
  if (IsNull())
    return true;
  // TODO(yosin): Position after anchor shouldn't be considered as at the
  // first editing position for node since that position resides outside of
  // the node.
  // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead of
  // DOM tree version.
  return IsAfterAnchorOrAfterChildren() ||
         offset_ >= EditingStrategy::LastOffsetForEditing(AnchorNode());
}

template <typename Strategy>
bool PositionTemplate<Strategy>::AtStartOfTree() const {
  if (IsNull())
    return true;
  return !Strategy::Parent(*AnchorNode()) && offset_ == 0;
}

template <typename Strategy>
bool PositionTemplate<Strategy>::AtEndOfTree() const {
  if (IsNull())
    return true;
  // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead of
  // DOM tree version.
  return !Strategy::Parent(*AnchorNode()) &&
         offset_ >= EditingStrategy::LastOffsetForEditing(AnchorNode());
}

// static
template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::InParentBeforeNode(
    const Node& node) {
  // FIXME: This should DCHECK(node.parentNode()). At least one caller currently
  // hits this DCHECK though, which indicates that the caller is trying to make
  // a position relative to a disconnected node (which is likely an error)
  // Specifically, editing/deleting/delete-ligature-001.html crashes with
  // DCHECK(node->parentNode())
  return PositionTemplate<Strategy>(Strategy::Parent(node),
                                    Strategy::Index(node));
}

// static
template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::InParentAfterNode(
    const Node& node) {
  DCHECK(node.parentNode()) << node;
  return PositionTemplate<Strategy>(Strategy::Parent(node),
                                    Strategy::Index(node) + 1);
}

// static
template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::BeforeNode(
    const Node& anchor_node) {
  return PositionTemplate<Strategy>(&anchor_node,
                                    PositionAnchorType::kBeforeAnchor);
}

// static
template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::AfterNode(
    const Node& anchor_node) {
  return PositionTemplate<Strategy>(&anchor_node,
                                    PositionAnchorType::kAfterAnchor);
}

// static
template <typename Strategy>
int PositionTemplate<Strategy>::LastOffsetInNode(const Node& node) {
  if (auto* data = DynamicTo<CharacterData>(node))
    return static_cast<int>(data->length());

  return static_cast<int>(Strategy::CountChildren(node));
}

// static
template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::FirstPositionInNode(
    const Node& anchor_node) {
  return PositionTemplate<Strategy>(anchor_node, 0);
}

// static
template <typename Strategy>
PositionTemplate<Strategy> PositionTemplate<Strategy>::LastPositionInNode(
    const Node& anchor_node) {
  if (anchor_node.IsTextNode()) {
    return PositionTemplate<Strategy>(anchor_node,
                                      LastOffsetInNode(anchor_node));
  }
  return PositionTemplate<Strategy>(&anchor_node,
                                    PositionAnchorType::kAfterChildren);
}

// static
template <typename Strategy>
PositionTemplate<Strategy>
PositionTemplate<Strategy>::FirstPositionInOrBeforeNode(const Node& node) {
  return EditingIgnoresContent(node) ? BeforeNode(node)
                                     : FirstPositionInNode(node);
}

// static
template <typename Strategy>
PositionTemplate<Strategy>
PositionTemplate<Strategy>::LastPositionInOrAfterNode(const Node& node) {
  return EditingIgnoresContent(node) ? AfterNode(node)
                                     : LastPositionInNode(node);
}

PositionInFlatTree ToPositionInFlatTree(const Position& pos) {
  if (pos.IsNull())
    return PositionInFlatTree();

  Node* const anchor = pos.AnchorNode();
  if (pos.IsOffsetInAnchor()) {
    if (anchor->IsCharacterDataNode())
      return PositionInFlatTree(anchor, pos.ComputeOffsetInContainerNode());
    DCHECK(!anchor->IsElementNode() || anchor->CanParticipateInFlatTree());
    int offset = pos.ComputeOffsetInContainerNode();
    if (!offset) {
      Node* node = anchor->IsShadowRoot() ? anchor->OwnerShadowHost() : anchor;
      return PositionInFlatTree::FirstPositionInNode(*node);
    }
    Node* child = NodeTraversal::ChildAt(*anchor, offset);
    if (!child) {
      Node* node = anchor->IsShadowRoot() ? anchor->OwnerShadowHost() : anchor;
      return PositionInFlatTree::LastPositionInNode(*node);
    }
    if (!child->CanParticipateInFlatTree()) {
      if (anchor->IsShadowRoot())
        return PositionInFlatTree(anchor->OwnerShadowHost(), offset);
      return PositionInFlatTree(anchor, offset);
    }
    if (Node* parent = FlatTreeTraversal::Parent(*child))
      return PositionInFlatTree(parent, FlatTreeTraversal::Index(*child));
    // When |pos| isn't appeared in flat tree, we map |pos| to after
    // children of shadow host.
    // e.g. "foo",0 in <progress>foo</progress>
    if (anchor->IsShadowRoot()) {
      return PositionInFlatTree::LastPositionInNode(*anchor->OwnerShadowHost());
    }
    return PositionInFlatTree::LastPositionInNode(*anchor);
  }

  if (anchor->IsShadowRoot())
    return PositionInFlatTree(anchor->OwnerShadowHost(), pos.AnchorType());
  DCHECK(anchor->CanParticipateInFlatTree());
  if (pos.IsBeforeAnchor() || pos.IsAfterAnchor()) {
    if (!FlatTreeTraversal::Parent(*anchor)) {
      // For Before/AfterAnchor, if |anchor| doesn't have parent in the flat
      // tree, there is no valid corresponding PositionInFlatTree.
      // Since this function is a primitive function, we do not adjust |pos|
      // to somewhere else in flat tree.
      // Reached by unit test
      // FrameSelectionTest.SelectInvalidPositionInFlatTreeDoesntCrash.
      return PositionInFlatTree();
    }
  }
  // TODO(yosin): Once we have a test case for SLOT or active insertion point,
  // this function should handle it.
  return PositionInFlatTree(anchor, pos.AnchorType());
}

PositionInFlatTree ToPositionInFlatTree(const PositionInFlatTree& position) {
  return position;
}

Position ToPositionInDOMTree(const Position& position) {
  return position;
}

Position ToPositionInDOMTree(const PositionInFlatTree& position) {
  if (position.IsNull())
    return Position();

  Node* anchor_node = position.AnchorNode();

  switch (position.AnchorType()) {
    case PositionAnchorType::kAfterChildren:
      // FIXME: When anchorNode is <img>, assertion fails in the constructor.
      return Position::LastPositionInNode(*anchor_node);
    case PositionAnchorType::kAfterAnchor:
      return Position::AfterNode(*anchor_node);
    case PositionAnchorType::kBeforeAnchor:
      return Position::BeforeNode(*anchor_node);
    case PositionAnchorType::kOffsetInAnchor: {
      int offset = position.OffsetInContainerNode();
      if (anchor_node->IsCharacterDataNode())
        return Position(anchor_node, offset);
      if (!offset)
        return Position::FirstPositionInNode(*anchor_node);
      Node* child = FlatTreeTraversal::ChildAt(*anchor_node, offset);
      if (child)
        return Position(child->parentNode(), child->NodeIndex());

      // |child| is null when the position is at the end of the children.
      // <div>foo|</div>
      return Position::LastPositionInNode(*anchor_node);
    }
    default:
      NOTREACHED();
      return Position();
  }
}

template <typename Strategy>
String PositionTemplate<Strategy>::ToAnchorTypeAndOffsetString() const {
  switch (AnchorType()) {
    case PositionAnchorType::kOffsetInAnchor: {
      StringBuilder builder;
      builder.Append("offsetInAnchor[");
      builder.AppendNumber(offset_);
      builder.Append("]");
      return builder.ToString();
    }
    case PositionAnchorType::kAfterChildren:
      return "afterChildren";
    case PositionAnchorType::kBeforeAnchor:
      return "beforeAnchor";
    case PositionAnchorType::kAfterAnchor:
      return "afterAnchor";
  }
  NOTREACHED();
  return g_empty_string;
}

#if DCHECK_IS_ON()

template <typename Strategy>
void PositionTemplate<Strategy>::ShowTreeForThis() const {
  if (!AnchorNode()) {
    LOG(INFO) << "\nposition is null";
    return;
  }
  LOG(INFO) << "\n"
            << AnchorNode()->ToTreeStringForThis().Utf8()
            << ToAnchorTypeAndOffsetString().Utf8();
}

template <typename Strategy>
void PositionTemplate<Strategy>::ShowTreeForThisInFlatTree() const {
  if (!AnchorNode()) {
    LOG(INFO) << "\nposition is null";
    return;
  }
  LOG(INFO) << "\n"
            << AnchorNode()->ToFlatTreeStringForThis().Utf8()
            << ToAnchorTypeAndOffsetString().Utf8();
}

#endif  // DCHECK_IS_ON()

template <typename PositionType>
static std::ostream& PrintPosition(std::ostream& ostream,
                                   const PositionType& position) {
  if (position.IsNull())
    return ostream << "null";
  return ostream << position.AnchorNode() << "@"
                 << position.ToAnchorTypeAndOffsetString().Utf8();
}

std::ostream& operator<<(std::ostream& ostream,
                         PositionAnchorType anchor_type) {
  switch (anchor_type) {
    case PositionAnchorType::kAfterAnchor:
      return ostream << "afterAnchor";
    case PositionAnchorType::kAfterChildren:
      return ostream << "afterChildren";
    case PositionAnchorType::kBeforeAnchor:
      return ostream << "beforeAnchor";
    case PositionAnchorType::kOffsetInAnchor:
      return ostream << "offsetInAnchor";
  }
  NOTREACHED();
  return ostream << "anchorType=" << static_cast<int>(anchor_type);
}

std::ostream& operator<<(std::ostream& ostream, const Position& position) {
  return PrintPosition(ostream, position);
}

std::ostream& operator<<(std::ostream& ostream,
                         const PositionInFlatTree& position) {
  return PrintPosition(ostream, position);
}

template class CORE_TEMPLATE_EXPORT PositionTemplate<EditingStrategy>;
template class CORE_TEMPLATE_EXPORT PositionTemplate<EditingInFlatTreeStrategy>;

}  // namespace blink

#if DCHECK_IS_ON()

void showTree(const blink::Position& pos) {
  pos.ShowTreeForThis();
}

void showTree(const blink::Position* pos) {
  if (pos)
    pos->ShowTreeForThis();
  else
    LOG(INFO) << "Cannot showTree for <null>";
}

#endif
