/*
 * Copyright (C) 2004, 2006, 2008 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.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_POSITION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_POSITION_H_

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/editing_strategy.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"

namespace blink {

class Node;
class TreeScope;

enum class PositionAnchorType : unsigned {
  kOffsetInAnchor,
  kBeforeAnchor,
  kAfterAnchor,
  kAfterChildren,
};

// Instances of |PositionTemplate<Strategy>| are immutable.
// TODO(editing-dev): Make constructor of |PositionTemplate| take |const Node*|.
template <typename Strategy>
class PositionTemplate {
  DISALLOW_NEW();

 public:
  PositionTemplate()
      : offset_(0), anchor_type_(PositionAnchorType::kOffsetInAnchor) {}

  static const TreeScope* CommonAncestorTreeScope(
      const PositionTemplate<Strategy>&,
      const PositionTemplate<Strategy>& b);
  static PositionTemplate<Strategy> EditingPositionOf(const Node* anchor_node,
                                                      int offset);

  // For creating before/after positions:
  PositionTemplate(const Node* anchor_node, PositionAnchorType);

  // For creating offset positions:
  PositionTemplate(const Node& anchor_node, int offset);
  // TODO(editing-dev): We should not pass |nullptr| as |anchor_node| for
  // |Position| constructor.
  // TODO(editing-dev): This constructor should eventually go away. See bug
  // http://wkb.ug/63040.
  PositionTemplate(const Node* anchor_node, int offset);

  PositionTemplate(const PositionTemplate&);

  // Returns a newly created |Position| with |kOffsetInAnchor|. |offset| can be
  // out of bound. Out of bound position is used for computing undo/redo
  // selection for merging text typing.
  static PositionTemplate<Strategy> CreateWithoutValidation(
      const Node& container,
      int offset);

  // TODO(editing-dev): Once we get a reason to use out of bound position,
  // we should change caller to use |CreateWithoutValidation()|.
  static PositionTemplate<Strategy> CreateWithoutValidationDeprecated(
      const Node& container,
      int offset);

  explicit operator bool() const { return IsNotNull(); }

  PositionAnchorType AnchorType() const { return anchor_type_; }
  bool IsAfterAnchor() const {
    return anchor_type_ == PositionAnchorType::kAfterAnchor;
  }
  bool IsAfterChildren() const {
    return anchor_type_ == PositionAnchorType::kAfterChildren;
  }
  bool IsBeforeAnchor() const {
    return anchor_type_ == PositionAnchorType::kBeforeAnchor;
  }
  bool IsBeforeChildren() const;
  bool IsOffsetInAnchor() const {
    return anchor_type_ == PositionAnchorType::kOffsetInAnchor;
  }

  // These are always DOM compliant values.  Editing positions like [img, 0]
  // (aka [img, before]) will return img->parentNode() and img->nodeIndex() from
  // these functions.

  // null for a before/after position anchored to a node with no parent
  Node* ComputeContainerNode() const;

  // O(n) for before/after-anchored positions, O(1) for parent-anchored
  // positions
  int ComputeOffsetInContainerNode() const;

  // Convenience method for DOM positions that also fixes up some positions for
  // editing
  PositionTemplate<Strategy> ParentAnchoredEquivalent() const;

  // Returns |PositionIsAnchor| type |Position| which is compatible with
  // |RangeBoundaryPoint| as safe to pass |Range| constructor. Return value
  // of this function is different from |parentAnchoredEquivalent()| which
  // returns editing specific position.
  PositionTemplate<Strategy> ToOffsetInAnchor() const;

  // Inline O(1) access for Positions which callers know to be parent-anchored
  int OffsetInContainerNode() const {
    DCHECK(IsOffsetInAnchor());
    return offset_;
  }

  // Returns an offset for editing based on anchor type for using with
  // |AnchorNode()| function:
  //   - kOffsetInAnchor  offset_
  //   - kBeforeAnchor    0
  //   - kAfterChildren   last editing offset in anchor node
  //   - kAfterAnchor     last editing offset in anchor node
  // Editing operations will change in anchor node rather than nodes around
  // anchor node.
  int ComputeEditingOffset() const;

  // These are convenience methods which are smart about whether the position is
  // neighbor anchored or parent anchored
  Node* ComputeNodeBeforePosition() const;
  Node* ComputeNodeAfterPosition() const;

  // Returns node as |Range::firstNode()|. This position must be a
  // |PositionAnchorType::OffsetInAhcor| to behave as |Range| boundary point.
  Node* NodeAsRangeFirstNode() const;

  // Similar to |nodeAsRangeLastNode()|, but returns a node in a range.
  Node* NodeAsRangeLastNode() const;

  // Returns a node as past last as same as |Range::pastLastNode()|. This
  // function is supposed to used in HTML serialization and plain text
  // iterator. This position must be a |PositionAnchorType::OffsetInAhcor| to
  // behave as |Range| boundary point.
  Node* NodeAsRangePastLastNode() const;

  Node* CommonAncestorContainer(const PositionTemplate<Strategy>&) const;

  Node* AnchorNode() const { return anchor_node_.Get(); }

  Document* GetDocument() const {
    return anchor_node_ ? &anchor_node_->GetDocument() : nullptr;
  }

  // For PositionInFlatTree, it requires an ancestor traversal to compute the
  // value of IsConnected(), which can be expensive.
  // TODO(crbug.com/761173): Rename to |ComputeIsConnected()| to indicate the
  // cost.
  bool IsConnected() const;

  bool IsValidFor(const Document&) const;

  bool IsNull() const { return !anchor_node_; }
  bool IsNotNull() const { return anchor_node_; }
  bool IsOrphan() const { return anchor_node_ && !IsConnected(); }

  // Note: Comparison of positions require both parameters are non-null. You
  // should check null-position before comparing them.
  // TODO(yosin): We should use |Position::operator<()| instead of
  // |Position::compareTo()| to utilize |DCHECK_XX()|.
  int16_t CompareTo(const PositionTemplate<Strategy>&) const;
  bool operator<(const PositionTemplate<Strategy>&) const;
  bool operator<=(const PositionTemplate<Strategy>&) const;
  bool operator>(const PositionTemplate<Strategy>&) const;
  bool operator>=(const PositionTemplate<Strategy>&) const;

  bool IsEquivalent(const PositionTemplate<Strategy>&) const;

  // These can be either inside or just before/after the node, depending on
  // if the node is ignored by editing or not.
  // FIXME: These should go away. They only make sense for legacy positions.
  bool AtFirstEditingPositionForNode() const;
  bool AtLastEditingPositionForNode() const;

  bool AtStartOfTree() const;
  bool AtEndOfTree() const;

  static PositionTemplate<Strategy> BeforeNode(const Node& anchor_node);
  static PositionTemplate<Strategy> AfterNode(const Node& anchor_node);
  static PositionTemplate<Strategy> InParentBeforeNode(const Node& anchor_node);
  static PositionTemplate<Strategy> InParentAfterNode(const Node& anchor_node);
  static int LastOffsetInNode(const Node& anchor_node);
  static PositionTemplate<Strategy> FirstPositionInNode(
      const Node& anchor_node);
  static PositionTemplate<Strategy> LastPositionInNode(const Node& anchor_node);
  static PositionTemplate<Strategy> FirstPositionInOrBeforeNode(
      const Node& anchor_node);
  static PositionTemplate<Strategy> LastPositionInOrAfterNode(
      const Node& anchor_node);

  String ToAnchorTypeAndOffsetString() const;
#if DCHECK_IS_ON()
  void ShowTreeForThis() const;
  void ShowTreeForThisInFlatTree() const;
#endif

  void Trace(Visitor*) const;

 private:
  bool IsAfterAnchorOrAfterChildren() const {
    return IsAfterAnchor() || IsAfterChildren();
  }

  // TODO(editing-dev): Since we should consider |Position| is constant in
  // tree, we should use |Member<const Node>|. see http://crbug.com/735327
  Member<Node> anchor_node_;
  // offset_ can be the offset inside anchor_node_, or if
  // EditingIgnoresContent(anchor_node_) returns true, then other places in
  // editing will treat offset_ == 0 as "before the anchor" and offset_ > 0 as
  // "after the anchor node".  See ParentAnchoredEquivalent for more info.
  int offset_;
  PositionAnchorType anchor_type_;
};

extern template class CORE_EXTERN_TEMPLATE_EXPORT
    PositionTemplate<EditingStrategy>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
    PositionTemplate<EditingInFlatTreeStrategy>;

using Position = PositionTemplate<EditingStrategy>;
using PositionInFlatTree = PositionTemplate<EditingInFlatTreeStrategy>;

template <typename Strategy>
bool operator==(const PositionTemplate<Strategy>& a,
                const PositionTemplate<Strategy>& b) {
  if (a.IsNull())
    return b.IsNull();

  if (a.AnchorNode() != b.AnchorNode() || a.AnchorType() != b.AnchorType())
    return false;

  if (!a.IsOffsetInAnchor()) {
    // Note: |offset_| only has meaning when
    // |PositionAnchorType::OffsetInAnchor|.
    return true;
  }

  // FIXME: In <div><img></div> [div, 0] != [img, 0] even though most of the
  // editing code will treat them as identical.
  return a.OffsetInContainerNode() == b.OffsetInContainerNode();
}

template <typename Strategy>
bool operator!=(const PositionTemplate<Strategy>& a,
                const PositionTemplate<Strategy>& b) {
  return !(a == b);
}

CORE_EXPORT PositionInFlatTree ToPositionInFlatTree(const Position&);
CORE_EXPORT PositionInFlatTree ToPositionInFlatTree(const PositionInFlatTree&);
CORE_EXPORT Position ToPositionInDOMTree(const Position&);
CORE_EXPORT Position ToPositionInDOMTree(const PositionInFlatTree&);

template <typename Strategy>
PositionTemplate<Strategy> FromPositionInDOMTree(const Position&);

template <>
inline Position FromPositionInDOMTree<EditingStrategy>(
    const Position& position) {
  return position;
}

template <>
inline PositionInFlatTree FromPositionInDOMTree<EditingInFlatTreeStrategy>(
    const Position& position) {
  return ToPositionInFlatTree(position);
}

CORE_EXPORT std::ostream& operator<<(std::ostream&, PositionAnchorType);
CORE_EXPORT std::ostream& operator<<(std::ostream&, const Position&);
CORE_EXPORT std::ostream& operator<<(std::ostream&, const PositionInFlatTree&);

}  // namespace blink

#if DCHECK_IS_ON()
// Outside the blink namespace for ease of invocation from gdb.
void showTree(const blink::Position&);
void showTree(const blink::Position*);
#endif

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_POSITION_H_
