/*
 * Copyright (C) 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 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 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 RangeBoundaryPoint_h
#define RangeBoundaryPoint_h

#include "core/dom/Node.h"
#include "core/dom/NodeTraversal.h"
#include "core/editing/Position.h"

namespace blink {

class RangeBoundaryPoint {
  DISALLOW_NEW();

 public:
  explicit RangeBoundaryPoint(Node& container);

  explicit RangeBoundaryPoint(const RangeBoundaryPoint&);

  bool IsConnected() const;
  const Position ToPosition() const;

  Node& Container() const;
  unsigned Offset() const;
  Node* ChildBefore() const;

  void Set(Node& container, unsigned offset, Node* child_before);
  void SetOffset(unsigned);

  void SetToBeforeChild(Node&);
  void SetToStartOfNode(Node&);
  void SetToEndOfNode(Node&);

  void ChildBeforeWillBeRemoved();
  void InvalidateOffset();
  void MarkValid() const;

  void Trace(blink::Visitor* visitor) {
    visitor->Trace(container_node_);
    visitor->Trace(child_before_boundary_);
  }

 private:
  uint64_t DomTreeVersion() const;
  void EnsureOffsetIsValid() const;
  bool IsOffsetValid() const;

  static const unsigned kInvalidOffset = static_cast<unsigned>(-1);

  Member<Node> container_node_;
  Member<Node> child_before_boundary_;
  mutable uint64_t dom_tree_version_;
  mutable unsigned offset_in_container_;
};

inline RangeBoundaryPoint::RangeBoundaryPoint(Node& container)
    : container_node_(container),
      child_before_boundary_(nullptr),
      dom_tree_version_(DomTreeVersion()),
      offset_in_container_(0) {}

inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
    : container_node_(other.Container()),
      child_before_boundary_(other.ChildBefore()),
      dom_tree_version_(other.dom_tree_version_),
      offset_in_container_(other.Offset()) {}

inline Node& RangeBoundaryPoint::Container() const {
  return *container_node_;
}

inline Node* RangeBoundaryPoint::ChildBefore() const {
  return child_before_boundary_.Get();
}

inline uint64_t RangeBoundaryPoint::DomTreeVersion() const {
  return container_node_->GetDocument().DomTreeVersion();
}

inline void RangeBoundaryPoint::EnsureOffsetIsValid() const {
  if (IsOffsetValid())
    return;
  DCHECK(!container_node_->IsCharacterDataNode());
  MarkValid();
  if (!child_before_boundary_) {
    offset_in_container_ = 0;
    return;
  }
  offset_in_container_ = child_before_boundary_->NodeIndex() + 1;
}

inline bool RangeBoundaryPoint::IsConnected() const {
  return container_node_ && container_node_->isConnected();
}

inline bool RangeBoundaryPoint::IsOffsetValid() const {
  if (offset_in_container_ == kInvalidOffset) {
    DCHECK(!container_node_->IsTextNode());
    return false;
  }
  return DomTreeVersion() == dom_tree_version_ ||
         container_node_->IsCharacterDataNode();
}

inline const Position RangeBoundaryPoint::ToPosition() const {
  EnsureOffsetIsValid();
  // TODO(yosin): We should return |Position::beforeAnchor| when
  // |m_containerNode| isn't |Text| node.
  return Position(container_node_.Get(), offset_in_container_);
}

inline unsigned RangeBoundaryPoint::Offset() const {
  EnsureOffsetIsValid();
  return offset_in_container_;
}

inline void RangeBoundaryPoint::Set(Node& container,
                                    unsigned offset,
                                    Node* child_before) {
  DCHECK_GE(offset, 0u);
  DCHECK_EQ(child_before,
            offset ? NodeTraversal::ChildAt(container, offset - 1) : nullptr);
  container_node_ = container;
  offset_in_container_ = offset;
  child_before_boundary_ = child_before;
  MarkValid();
}

inline void RangeBoundaryPoint::SetOffset(unsigned offset) {
  DCHECK(container_node_);
  DCHECK(container_node_->IsCharacterDataNode());
  DCHECK_GE(offset_in_container_, 0u);
  DCHECK(!child_before_boundary_);
  offset_in_container_ = offset;
  MarkValid();
}

inline void RangeBoundaryPoint::SetToBeforeChild(Node& child) {
  DCHECK(child.parentNode());
  child_before_boundary_ = child.previousSibling();
  container_node_ = child.parentNode();
  offset_in_container_ = child_before_boundary_ ? kInvalidOffset : 0;
  MarkValid();
}

inline void RangeBoundaryPoint::SetToStartOfNode(Node& container) {
  container_node_ = &container;
  offset_in_container_ = 0;
  child_before_boundary_ = nullptr;
  MarkValid();
}

inline void RangeBoundaryPoint::SetToEndOfNode(Node& container) {
  container_node_ = &container;
  if (container_node_->IsCharacterDataNode()) {
    offset_in_container_ = container_node_->MaxCharacterOffset();
    child_before_boundary_ = nullptr;
  } else {
    child_before_boundary_ = container_node_->lastChild();
    offset_in_container_ = child_before_boundary_ ? kInvalidOffset : 0;
  }
  MarkValid();
}

inline void RangeBoundaryPoint::ChildBeforeWillBeRemoved() {
  child_before_boundary_ = child_before_boundary_->previousSibling();
  if (!IsOffsetValid())
    return;
  DCHECK_GT(offset_in_container_, 0u);
  if (!child_before_boundary_)
    offset_in_container_ = 0;
  else if (offset_in_container_ > 0)
    --offset_in_container_;
  MarkValid();
}

inline void RangeBoundaryPoint::InvalidateOffset() {
  offset_in_container_ = kInvalidOffset;
}

inline void RangeBoundaryPoint::MarkValid() const {
  dom_tree_version_ = DomTreeVersion();
}

inline bool operator==(const RangeBoundaryPoint& a,
                       const RangeBoundaryPoint& b) {
  if (a.Container() != b.Container())
    return false;
  if (a.ChildBefore() || b.ChildBefore()) {
    if (a.ChildBefore() != b.ChildBefore())
      return false;
  } else {
    if (a.Offset() != b.Offset())
      return false;
  }
  return true;
}

}  // namespace blink

#endif
