// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VERIBLE_COMMON_UTIL_VECTOR_TREE_H_
#define VERIBLE_COMMON_UTIL_VECTOR_TREE_H_

#include <algorithm>
#include <cstddef>
#include <functional>
#include <iosfwd>  // IWYU pragma: keep
#include <iterator>
#include <set>
#include <utility>
#include <vector>

#include "common/util/iterator_range.h"
#include "common/util/logging.h"
#include "common/util/spacer.h"

namespace verible {

// This helper class contains private template functions for many pairs
// of const/mutable methods of VectorTree.  This reduces the amount of code
// duplication for similar methods.
// In all template functions, type TP is either 'VectorTree' or
// 'const VectorTree', and is inferrable from template argument deduction.
// Recursive calls automatically call the correct variant.
class _VectorTreeImpl {
 protected:
  // Returns pointer root node, following ancestry chain.
  template <typename TP>
  static TP* _Root(TP* node) {
    while (node->Parent() != nullptr) {
      node = node->Parent();
    }
    return node;
  }

  // Returns pointer to next sibling if it exists, else nullptr.
  template <typename TP>
  static TP* _NextSibling(TP* node) {
    if (node->Parent() == nullptr) {
      return nullptr;
    }
    const size_t birth_rank = node->BirthRank();
    const size_t next_rank = birth_rank + 1;
    if (next_rank == node->Parent()->Children().size()) {
      return nullptr;  // This is the last child of the Parent().
    }
    // More children follow this one.
    return &node->Parent()->Children()[next_rank];
  }

  // Returns pointer to previous sibling if it exists, else nullptr.
  template <typename TP>
  static TP* _PreviousSibling(TP* node) {
    if (node->Parent() == nullptr) {
      return nullptr;
    }
    const size_t birth_rank = node->BirthRank();
    if (birth_rank == 0) {
      return nullptr;
    }
    // More children precede this one.
    return &node->Parent()->Children()[birth_rank - 1];
  }

  // Descend through children using indices specified by iterator range.
  // Iter type dereferences to an integral value.
  // This works on any internal node, not just the root.
  template <typename TP, typename Iter>
  static TP& _DescendPath(TP* node, Iter start, Iter end) {
    for (; start != end; ++start) {
      auto& children = node->Children();
      node = &children[*start];  // descend
    }
    return *node;
  }

  // Returns the node reached by descending through Children().front().
  template <typename TP>
  static TP* _LeftmostDescendant(TP* node) {
    while (!node->Children().empty()) {
      node = &node->Children().front();
    }
    return node;
  }

  // Returns the node reached by descending through Children().back().
  template <typename TP>
  static TP* _RightmostDescendant(TP* node) {
    while (!node->Children().empty()) {
      node = &node->Children().back();
    }
    return node;
  }

  // Navigates to the next leaf (node without Children()) in the tree
  // (if it exists), else returns nullptr.
  template <typename TP>
  static TP* _NextLeaf(TP* node) {
    auto* parent = node->Parent();
    if (parent == nullptr) {
      // Root node has no next sibling, this is the end().
      return nullptr;
    }

    // Find the next sibling, if there is one.
    auto& siblings = parent->Children();
    const size_t birth_rank = node->BirthRank();
    const size_t next_rank = birth_rank + 1;
    if (next_rank != siblings.size()) {
      // More children follow this one.
      return siblings[next_rank].LeftmostDescendant();
    }

    // This is the last child of the group.
    // Find the nearest parent that has a next child (ascending).
    // TODO(fangism): rewrite without recursion
    auto* next_ancestor = parent->NextLeaf();
    if (next_ancestor == nullptr) return nullptr;

    // next_ancestor is the NearestCommonAncestor() to the original
    // node and the resulting node.
    return next_ancestor->LeftmostDescendant();
  }

  // Navigates to the previous leaf (node without Children()) in the tree
  // (if it exists), else returns nullptr.
  template <typename TP>
  static TP* _PreviousLeaf(TP* node) {
    auto* parent = node->Parent();
    if (parent == nullptr) {
      // Root node has no previous sibling, this is the reverse-end().
      return nullptr;
    }

    // Find the next sibling, if there is one.
    auto& siblings = parent->Children();
    const size_t birth_rank = node->BirthRank();
    if (birth_rank > 0) {
      // More children precede this one.
      return siblings[birth_rank - 1].RightmostDescendant();
    }

    // This is the first child of the group.
    // Find the nearest parent that has a previous child (descending).
    // TODO(fangism): rewrite without recursion
    auto* prev_ancestor = parent->PreviousLeaf();
    if (prev_ancestor == nullptr) return nullptr;

    // prev_ancestor is the NearestCommonAncestor() to the original
    // node and the resulting node.
    return prev_ancestor->RightmostDescendant();
  }

  // Returns the nearest common ancestor node to two nodes if a common ancestor
  // exists, else nullptr.
  // Run time: let L and R be the number of ancestors of left and right,
  // respectively.  In the worst case, there will be L and R set insertions,
  // so O(L lg L) + I(R lg R) and L and R membership checks, so O(L lg R) + O(R
  // lg L).  With K = max(L, R), overall this is no worse than O(K lg K).
  template <typename TP>
  static TP* _NearestCommonAncestor(TP* left, TP* right) {
    std::set<TP*> left_ancestors, right_ancestors;
    // In alternation, insert left/right into its respective set of ancestors,
    // and check for membership in the other ancestor set.
    // Return as soon as one is found in the other's set of ancestors.
    while (left != nullptr || right != nullptr) {
      if (left != nullptr) {
        left_ancestors.insert(left);
        if (right_ancestors.find(left) != right_ancestors.end()) {
          return left;
        }
        left = left->Parent();
      }
      if (right != nullptr) {
        right_ancestors.insert(right);
        if (left_ancestors.find(right) != left_ancestors.end()) {
          return right;
        }
        right = right->Parent();
      }
    }
    // Once this point is reached, there are no common ancestors.
    return nullptr;
  }
};

// VectorTree is a hierarchical representation of information.
// While it may be useful to maintain some invariant relationship between
// parents and children nodes, it is not required for this class.
// The traversal methods ApplyPreOrder/ApplyPostOrder could be used to
// maintain or verify parent-child invariants.
// The VectorTree class is itself also the same as the internally used node
// class; i.e. there is no separate node class.
//
// Example applications (with some parent-child invariant relationship):
//
// * Range interval tree -- A numeric range from [0:N] could be sub-divided
//   into smaller ranges [0:k], [k:N] for some 0 < k < N, or multiple
//   monotonically increasing k's.  This class is a generalization of an
//   interval tree concept.
//
// * Lexical tokens output -- some tokens could be further tokenized or
//   expanded, but the choice of view depends on consumer and application.
//   This can be useful for embedding snippets of one language within another;
//   further lexing/parsing of an unexpanded substring can be deferred.
//
// * Lexical token range partitions -- token sub-range partitioning is a
//   critical step in a formatting strategy; the decision to partition
//   a particular range may be difficult to determine statically, so it
//   is best left undecided until a later heuristic pass.
//
// Construction:
// This implementation gives the user the liberty to construct the tree
// nodes in any order and any manner.  A top-down construction may guarantee
// that a parent is well-formed before creating its children, whereas a
// bottom-up construction completes creation of children before the enveloping
// parent.
template <typename T>
class VectorTree : private _VectorTreeImpl {
  typedef VectorTree<T> this_type;

  // Self-recursive type that represents children in an expanded view.
  typedef std::vector<this_type> subnodes_type;

  typedef _VectorTreeImpl impl_type;

  // Private default constructor.
  VectorTree() = default;

 public:
  typedef T value_type;

  // Deep copy-constructor.
  VectorTree(const this_type& other)
      : node_value_(other.node_value_),
        children_(other.children_),
        parent_(other.parent_) {
    Relink();
  }

  VectorTree(this_type&& other)
      : node_value_(std::move(other.node_value_)),
        children_(std::move(other.children_)),
        parent_(other.parent_) {
    Relink();
  }

  // This constructor can be used to recursively build trees.
  // e.g.
  //   // looks like function-call, but just invokes constructor:
  //   typedef VectorTree<Foo> FooNode;
  //   auto foo_tree = FooNode({value-initializer},
  //        FooNode({value-initializer}, /* children nodes... */ ),
  //        FooNode({value-initializer}, /* children nodes... */ )
  //   );
  template <typename... Args>
  explicit VectorTree(const value_type& v, Args&&... args)
      : node_value_(v), children_() {
    AdoptSubtree(std::forward<Args>(args)...);
  }

  template <typename... Args>
  explicit VectorTree(value_type&& v, Args&&... args)
      : node_value_(std::move(v)), children_() {
    AdoptSubtree(std::forward<Args>(args)...);
  }

  ~VectorTree() { CHECK(CheckIntegrity()); }

  // Swaps values and subtrees of two nodes.
  // This operation is safe for unrelated trees (no common ancestor).
  // This operation is safe when the two nodes share a common ancestor,
  // excluding the case where one node is a direct ancestor of the other.
  // TODO(fangism): Add a proper check for this property, and test.
  void swap(this_type& other) {
    // parent_'s are unchanged.
    std::swap(node_value_, other.node_value_);
    children_.swap(other.children_);  // efficient O(1) vector::swap
    Relink();                         // O(|children|)
    other.Relink();                   // O(|children|)
  }

  // Copy value and children, but relink new children to this node.
  VectorTree& operator=(const this_type& source) {
    node_value_ = source.node_value_;
    children_ = source.Children();
    Relink();
    return *this;
  }

  // Explicit move-assignability needed for vector::erase()
  // No need to change parent links when children keep same parent.
  VectorTree& operator=(this_type&& source) {
    // Keep this->parent_.  Ignore source.parent_.

    node_value_ = std::move(source.node_value_);

    children_.clear();
    // vector::swap only moves pointers, not elements
    children_.swap(source.children_);
    Relink();  // because the address of 'this' changes.
    return *this;
  }

  // Builders

  // Appends a new child node to the tree at this level.
  // 'this' node is the parent of the new child.
  // Returns a pointer to the newly added child.
  // This invalidates previous iterators/pointers to sibling children.
  template <typename... Args>
  this_type* NewChild(Args&&... args) {
    // emplace_back() may cause realloc
    children_.emplace_back(std::forward<Args>(args)...);
    // Relink child to parent.
    auto& newest = children_.back();
    newest.parent_ = this;
    return &newest;
  }

  // Appends a new child node to the parent of this node.
  // Returns a pointer to the newly added sibling.
  // This invalidates previous iterators/pointers to sibling children.
  template <typename... Args>
  this_type* NewSibling(Args&&... args) {
    return ABSL_DIE_IF_NULL(parent_)->NewChild(std::forward<Args>(args)...);
  }

  // No-op base case for variadic AdoptSubtree.
  void AdoptSubtree() const {}

  // Appends one or more sub-trees at this level.
  // Variadic template handles one argument at a time.
  // This invalidates previous iterators/pointers to sibling children.
  template <typename F, typename... Args>
  void AdoptSubtree(F&& first, Args&&... args) {
    children_.emplace_back(std::forward<F>(first));  // may cause realloc
    // Relink child to parent.
    auto& newest = children_.back();
    newest.parent_ = this;
    AdoptSubtree(std::forward<Args>(args)...);
  }

  // This node takes/moves subtrees from another node (concatenates).
  // There need not be any relationship between this node and the other.
  void AdoptSubtreesFrom(this_type* other) {
    auto& src_children = other->Children();
    children_.reserve(children_.size() + src_children.size());
    AdoptSubtreesFromUnreserved(&src_children);
  }

  // Accessors

  T& Value() { return node_value_; }

  const T& Value() const { return node_value_; }

  this_type* Parent() { return parent_; }

  const this_type* Parent() const { return parent_; }

  subnodes_type& Children() { return children_; }

  const subnodes_type& Children() const { return children_; }

  // Properties

  // Returns the index of this node relative to parent's children.
  // An only-child or first-child will have birth rank 0.
  size_t BirthRank() const {
    if (parent_ != nullptr) {
      // Parent() must have Children(); this is one of them.
      // Storage of siblings must be contiguous, so that pointer
      // distance translates to index.
      return std::distance(&Parent()->Children().front(), this);
    }
    return 0;
  }

  // Returns the number of parents between this node and the root.
  size_t NumAncestors() const {
    size_t depth = 0;
    for (const this_type* iter = Parent(); iter != nullptr;
         iter = iter->Parent()) {
      ++depth;
    }
    return depth;
  }

  // Returns true if 'other' is an ancestor of this node, in other words,
  // this node is descended from 'other'.
  // This method could have been named IsDescendedFrom().
  // nullptr is never considered an ancestor of any node.
  // 'this' node is not considered an ancestor of itself.
  bool ContainsAncestor(const this_type* other) const {
    if (other == nullptr) return false;
    for (const this_type* iter = Parent(); iter != nullptr;
         iter = iter->Parent()) {
      if (iter == other) return true;
    }
    return false;
  }

  // Returns pointer to the tree root, the greatest ancestor of this node.
  const this_type* Root() const { return impl_type::_Root(this); }

  // Returns mutable pointer to the tree root.
  this_type* Root() { return impl_type::_Root(this); }

  // Returns the closest common ancestor to this and the other, else nullptr.
  // This is the const pointer overload.
  const this_type* NearestCommonAncestor(const this_type* other) const {
    return impl_type::_NearestCommonAncestor(this, other);
  }

  // Returns the closest common ancestor to this and the other, else nullptr.
  // This is the mutable pointer overload.
  this_type* NearestCommonAncestor(this_type* other) {
    return impl_type::_NearestCommonAncestor(this, other);
  }

  // Construct a path of BirthRank()s from root to this.
  // Root node's 'path' is empty.  Passing the resulting path to
  // root.DescendPath() gets you back to this node.
  // PathType can be any container with a push_back() interface.
  template <class PathType>
  void Path(PathType& path) const {
    if (Parent() != nullptr) {
      Parent()->Path(path);
      path.push_back(BirthRank());
    }
  }

  // Descend through children using indices specified by iterator range.
  // Iter type dereferences to an integral value.
  // This works on any internal node, not just the root.
  template <class Iter>
  const this_type& DescendPath(Iter start, Iter end) const {
    return impl_type::_DescendPath(this, start, end);
  }

  // Returns the next sibling node if it exists, else nullptr.
  const this_type* NextSibling() const { return impl_type::_NextSibling(this); }

  // Returns the next sibling node if it exists, else nullptr.
  this_type* NextSibling() { return impl_type::_NextSibling(this); }

  // Returns the previous sibling node if it exists, else nullptr.
  const this_type* PreviousSibling() const {
    return impl_type::_PreviousSibling(this);
  }

  // Returns the previous sibling node if it exists, else nullptr.
  this_type* PreviousSibling() { return impl_type::_PreviousSibling(this); }

  // Mutable variant of DescendPath.
  template <class Iter>
  this_type& DescendPath(Iter start, Iter end) {
    return impl_type::_DescendPath(this, start, end);
  }

  // Returns the node reached by descending through Children().front().
  const this_type* LeftmostDescendant() const {
    return impl_type::_LeftmostDescendant(this);
  }

  // Returns the node reached by descending through Children().front(), mutable
  // variant.
  this_type* LeftmostDescendant() {
    return impl_type::_LeftmostDescendant(this);
  }

  // Returns the node reached by descending through Children().back().
  const this_type* RightmostDescendant() const {
    return impl_type::_RightmostDescendant(this);
  }

  // Returns the node reached by descending through Children().back(), mutable
  // variant.
  this_type* RightmostDescendant() {
    return impl_type::_RightmostDescendant(this);
  }

  // Returns true if this node has no parent, or it has BirthRank 0.
  bool IsFirstChild() const {
    if (Parent() == nullptr) return true;
    return BirthRank() == 0;
  }

  // Returns true if this node has no parent, or it is the last child of its
  // parent.
  bool IsLastChild() const {
    if (Parent() == nullptr) return true;
    return BirthRank() == Parent()->Children().size() - 1;
  }

  // Navigates to the next leaf (node without Children()) in the tree
  // (if it exists), else returns nullptr.
  const this_type* NextLeaf() const { return impl_type::_NextLeaf(this); }

  // Mutable variant of NextLeaf().
  this_type* NextLeaf() { return impl_type::_NextLeaf(this); }

  // Navigates to the previous leaf (node without Children()) in the tree
  // (if it exists), else returns nullptr.
  const this_type* PreviousLeaf() const {
    return impl_type::_PreviousLeaf(this);
  }

  // Mutable variant of PreviousLeaf().
  this_type* PreviousLeaf() { return impl_type::_PreviousLeaf(this); }

  // Removes this node from its parent, and shifts ths siblings that follow this
  // node lower in BirthRank().
  // Any iterators that pointed to this node or its later siblings are
  // invalidated.
  // This node is destroyed in the process.
  // This operation is only valid on non-root nodes.
  // It is the caller's responsibility to maintain invariants before
  // destroying this node.
  void RemoveSelfFromParent() {
    auto& siblings = ABSL_DIE_IF_NULL(Parent())->Children();
    auto self_iter = siblings.begin() + BirthRank();
    CHECK_EQ(&*self_iter, this);
    siblings.erase(self_iter);
  }

  // TODO(fangism): provide unidirectional iterator views, forward and reversed,
  // using NextLeaf() and PreviousLeaf().

  // Returns true if parent-child links are valid in entire tree.
  bool CheckIntegrity() const {
    for (const auto& child : children_) {
      CHECK_EQ(child.Parent(), this)
          << "Inconsistency: child's parent does not point back to this node!";
      if (!child.CheckIntegrity()) return false;
    }
    return true;
  }

  // Function-application traversals.
  //   * Apply in pre-order vs. post-order.
  //   * Apply to attached value at each node vs. the whole node itself.
  //     Whole node gives access to immediate children (and subtree).
  //   * Apply function is const vs. mutating.
  // All combinations of the above are provided.

  // Visits all tree nodes in pre-order traversal applying function to all nodes
  // (non-modifying).  Useful for checking invariants between parents and
  // their children.
  void ApplyPreOrder(const std::function<void(const this_type&)>& f) const {
    f(*this);
    for (const auto& child : Children()) {
      child.ApplyPreOrder(f);
    }
  }

  // This variant of ApplyPreOrder expects a function on the underlying
  // value_type (const&).
  void ApplyPreOrder(const std::function<void(const value_type&)>& f) const {
    ApplyPreOrder([&f](const this_type& t) { f(t.Value()); });
  }

  // Visits all tree nodes in pre-order traversal applying function to all nodes
  // (modifying).
  void ApplyPreOrder(const std::function<void(this_type&)>& f) {
    f(*this);
    for (auto& child : Children()) {
      child.ApplyPreOrder(f);
    }
  }

  // Visits all tree nodes in pre-order traversal applying function to all node
  // values (modifying).  Useful for applying transformations.
  void ApplyPreOrder(const std::function<void(value_type&)>& f) {
    ApplyPreOrder([&f](this_type& t) { f(t.Value()); });
  }

  // Visits all tree nodes in post-order traversal applying function to all
  // nodes (non-modifying).  Useful for checking invariants between parents and
  // their children.
  void ApplyPostOrder(const std::function<void(const this_type&)>& f) const {
    for (const auto& child : Children()) {
      child.ApplyPostOrder(f);
    }
    f(*this);
  }

  // This variant of ApplyPostOrder expects a function on the underlying
  // value_type (const&).
  void ApplyPostOrder(const std::function<void(const value_type&)>& f) const {
    ApplyPostOrder([&f](const this_type& t) { f(t.Value()); });
  }

  // Visits all tree nodes in post-order traversal applying function to all
  // nodes (modifying).  Useful for applying transformations.
  void ApplyPostOrder(const std::function<void(this_type&)>& f) {
    for (auto& child : Children()) {
      child.ApplyPostOrder(f);
    }
    f(*this);
  }

  // Visits all tree nodes in post-order traversal applying function to all node
  // values (modifying).  Useful for applying transformations.
  void ApplyPostOrder(const std::function<void(value_type&)>& f) {
    ApplyPostOrder([&f](this_type& t) { f(t.Value()); });
  }

  // Recursively transform a VectorTree<T> to VectorTree<S>.
  // This cannot be expressed as a constructor because template constructor
  // calls must be type-deducible from its constructor args, and there's no
  // way to explicitly invoke a constructor with specific template args.
  // The resulting tree is always StructureEqual() to the original tree.
  //
  // Usage:
  //   auto tree_other = orig_tree.Transform<OtherType>(
  //       [](const VectorTree<OrigType>& node) { return ... });
  template <typename S>
  VectorTree<S> Transform(
      const std::function<S(const this_type& node)>& f) const {
    VectorTree<S> return_tree(f(*this));  // sets Value()
    auto& return_children = return_tree.Children();
    return_children.reserve(Children().size());
    // Construct children subtree.
    for (const auto& child : Children()) {
      return_tree.AdoptSubtree(child.template Transform<S>(f));
    }
    return return_tree;  // Rely on copy-elision.
  }

  // If this node has exactly one child, replace this node with that child
  // and return true, otherwise, do nothing and return false.
  bool HoistOnlyChild() {
    if (Children().size() != 1) return false;

    auto& only = Children().front();
    only.parent_ = nullptr;  // disconnect from parent
    std::swap(node_value_, only.node_value_);

    // children_.swap(only.children_);  // but this leaks
    // so we swap through a temporary, which still avoids any copying.
    subnodes_type temp;
    temp.swap(only.children_);
    children_.swap(temp);

    Relink();
    return true;
  }

  // Combines the Nth and (N+1) sibling using a custom function 'joiner' on the
  // nodes' values, and the Nth sibling will adopt N+1's children.
  // The 'joiner' function does: *left = f(*left, *right);
  // The (N+1) sibling will be erased in the process, and every sibling
  // thereafter will be shifted back one position (same inefficiency as shifting
  // vector contents).  This invalidates all iterators after position N,
  // and iterators to the Nth node's children (possible realloc).
  void MergeConsecutiveSiblings(
      size_t N, std::function<void(value_type*, const value_type&)> joiner) {
    CHECK_LT(N + 1, children_.size());

    // Combine value into node[N].
    joiner(&Children()[N].node_value_, Children()[N + 1].node_value_);

    // Move-concatenate children to node[N].
    const auto next_iter = children_.begin() + N + 1;
    Children()[N].AdoptSubtreesFrom(&*next_iter);

    // Shift-left children_ by 1 beyond N.
    children_.erase(next_iter);  // done via move-assignment
  }

  // Replace all direct children of this node with concatenated grandchildren.
  // Retains the value of this node.  Discards direct childrens' values.
  void FlattenOnce() {
    // Emancipate children from this node without discarding them yet.
    subnodes_type temp;
    temp.swap(children_);

    // Reserve space for all grandchildren.
    {
      size_t num_grandchildren = 0;
      for (const auto& child : temp) {
        num_grandchildren += child.Children().size();
      }
      children_.reserve(num_grandchildren);
    }

    // Concatenate all grandchildren.
    for (auto& child : temp) {
      AdoptSubtreesFromUnreserved(&child.Children());
    }

    // temp, which holds the discarded children, is destroyed.
  }

  // For every child, if that child has grandchildren, replace that child with
  // its grandchildren, else preserve that child.
  // If new_offsets is provided, populate that array with indices into the
  // resulting children that correspond to the start locations of the original
  // children's children.  This lets the caller reference and operate on
  // subranges of the original set of grandchildren.
  void FlattenOnlyChildrenWithChildren(
      std::vector<size_t>* new_offsets = nullptr) {
    // Emancipate children from this node without discarding them yet.
    subnodes_type temp;
    temp.swap(children_);

    // Reserve space.
    {
      if (new_offsets != nullptr) {
        new_offsets->clear();
        new_offsets->reserve(temp.size());
      }
      size_t num_grandchildren = 0;
      for (const auto& child : temp) {
        if (new_offsets != nullptr) new_offsets->push_back(num_grandchildren);
        num_grandchildren += std::max(child.Children().size(), size_t(1));
      }
      children_.reserve(num_grandchildren);
    }

    // Concatenate children-without-grandchildren and grandchildren.
    for (auto& child : temp) {
      if (child.Children().empty()) {
        children_.emplace_back(std::move(child));
      } else {
        AdoptSubtreesFromUnreserved(&child.Children());
      }
    }

    // temp, which holds the discarded children, is destroyed.
  }

  // Replace the i'th child with its children.  This may result in increasing
  // the number of direct children of this node.
  void FlattenOneChild(size_t i) {
    const size_t original_size = Children().size();
    CHECK_LT(i, original_size);
    // Unlink the grandchildren that will be adopted (in staging area).
    subnodes_type adopted_grandchildren;
    adopted_grandchildren.swap(Children()[i].Children());
    {
      // Remove i'th child.
      const auto insert_iter = children_.begin() + i;
      children_.erase(insert_iter);
      // Allocate room for new children.
      this_type dummy_node;
      children_.insert(insert_iter, adopted_grandchildren.size(), dummy_node);
      // insert_iter is invalidated here, due to potential re-allocation
    }
    {
      // Insert adopted grandchildren (via move-swap to avoid copying).
      const auto insert_iter = children_.begin() + i;
      std::swap_ranges(adopted_grandchildren.begin(),
                       adopted_grandchildren.end(), insert_iter);
      // Relink them to this node.
      for (auto& child : verible::make_range(
               insert_iter, insert_iter + adopted_grandchildren.size())) {
        child.parent_ = this;
      }
    }
  }

  // Pretty-print in tree-form.  Value() is enclosed in parens, and the whole
  // node is enclosed in braces.
  std::ostream& PrintTree(std::ostream* stream, size_t indent = 0) const {
    *stream << Spacer(indent) << "{ (" << Value() << ')';
    if (Children().empty()) {
      *stream << " }";
    } else {
      *stream << '\n';
      for (const auto& child : Children()) {
        child.PrintTree(stream, indent + 2) << '\n';
      }
      *stream << Spacer(indent) << '}';
    }
    return *stream;
  }

 private:
  // Establish parent-child links.
  void Relink() {
    for (auto& child : children_) {
      child.parent_ = this;
    }
  }

  // This node takes/moves subtrees from another array of node (concatenates).
  void AdoptSubtreesFromUnreserved(subnodes_type* other) {
    for (auto& child : *other) {
      AdoptSubtree(std::move(child));  // already Relink()s
    }
    other->clear();
  }

  // Singular value stored at this node.
  value_type node_value_;

  // Array of nodes/subtrees.
  subnodes_type children_;

  // Pointer up to parent node.
  // Only the root node of a tree has a nullptr parent_.
  this_type* parent_ = nullptr;
};

// Stream-printable representation of the location of a node under its
// greatest ancestor (root).
// Usage: stream << NodePath(vector_tree);
struct NodePath {
  template <class T>
  explicit NodePath(const VectorTree<T>& node) {
    node.Path(path);
  }
  std::vector<size_t> path;
};

std::ostream& operator<<(std::ostream& stream, const NodePath& p);

template <typename T>
std::ostream& operator<<(std::ostream& stream, const VectorTree<T>& node) {
  return node.PrintTree(&stream);
}

// Binary operations

// Struct used to point to corresponding two nodes in different trees.
// This could be interpreted as a difference object.
// Both pointers should be nullptr when DeepEqual() finds no differences between
// any corresponding pair of tree nodes, or non-nullptr when some difference is
// found.  When they are both non-nullptr, left != right by some user-defined
// comparison function, and their ->Path()s are equivalent (as ensured by
// DeepEqual's simultaneous traversal).
// This is analogous to std::mismatch()'s return type: a pair of non-end()
// iterators pointing to the first difference found in a dual-linear
// traversal.
template <typename LT, typename RT>
struct VectorTreeNodePair {
  VectorTreeNodePair() {}
  VectorTreeNodePair(const LT* l, const RT* r) : left(l), right(r) {}
  const LT* left = nullptr;
  const RT* right = nullptr;
};

// Recursively compares two trees node-for-node, checking their values
// and substructure.  The value types of the trees being compared need not be
// the same, as long as there exists a comparison function for them.
// The comparison function should be an equality function, i.e. it should
// return true when values are considered equal, otherwise false.
// Traversal order: pre-order (compare parents before children)
// Returns pair of pointers pointing to first encountered difference,
// or pair of nullptr when everything matches.
// If you want more detail about value differences, then capture them in the
// comparison function's closure before returning.
template <typename LT, typename RT>
VectorTreeNodePair<LT, RT> DeepEqual(
    const LT& left, const RT& right,
    const std::function<bool(const typename LT::value_type&,
                             const typename RT::value_type&)>& comp) {
  using result_type = VectorTreeNodePair<LT, RT>;
  // Node value comparison at current level.
  if (!comp(left.Value(), right.Value())) {
    return result_type{&left, &right};
  }

  // Subtree comparison: check number of children first, returning early if
  // different.
  const auto& left_children = left.Children();
  const auto& right_children = right.Children();
  if (left_children.size() != right_children.size()) {
    return result_type{&left, &right};
  }

  // Number of children match.  Find first differing children.
  // The iterators returned by std::mismatch() do not propagate the
  // deep children nodes that differ, so we must use a lambda with capture.
  result_type first_diff;  // initially nullptrs
  std::mismatch(left_children.begin(), left_children.end(),
                right_children.begin(),
                [&comp, &first_diff](const LT& l, const RT& r) -> bool {
                  const auto result = DeepEqual(l, r, comp);
                  if (result.left == nullptr) {
                    return true;
                  } else {
                    first_diff = result;  // Capture first difference.
                    return false;
                  }
                  // When this returns true, no further comparisons will be
                  // called, so the assignment to first_diff will contain the
                  // desired result.
                });
  // When every subtree matches, first_diff will hold nullptrs.
  // Otherwise it will point to the first mismatched nodes.
  return first_diff;
}

// Overload for the case when left and right tree types have a defined equality
// operator.  This also works when the left and right types are the same.
template <typename LT, typename RT>
VectorTreeNodePair<LT, RT> DeepEqual(const LT& left, const RT& right) {
  return DeepEqual(left, right,
                   [](const typename LT::value_type& l,
                      const typename RT::value_type& r) { return l == r; });
}

// If both trees are structurally the same, node-for-node, returns a pair of
// nullptrs.  Otherwise, returns with pointers to the first encountered nodes
// that differ in substructure.  Traversal order: pre-order.
// Implementation: this is just a degenerate form of DeepEqual, where the value
// comparison is ignored (always returns true).
template <typename LT, typename RT>
VectorTreeNodePair<LT, RT> StructureEqual(const LT& left, const RT& right) {
  // Ignore node values by always treating them as equal.
  return DeepEqual(left, right,
                   [](const typename LT::value_type&,
                      const typename RT::value_type&) { return true; });
}

// Provide ADL-enabled overload for use by swap implementations.
template <class T>
void swap(VectorTree<T>& left, VectorTree<T>& right) {
  left.swap(right);
}

}  // namespace verible

#endif  // VERIBLE_COMMON_UTIL_VECTOR_TREE_H_
