// 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_MAP_TREE_H_
#define VERIBLE_COMMON_UTIL_MAP_TREE_H_

#include <cstddef>
#include <functional>
#include <iostream>
#include <map>
#include <utility>

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

namespace verible {

// MapTree is a hierarchical tree representation of values, where branches are
// associated with keys.
// This is one implementation of a 'trie' or 'prefix tree' data structure.
// There are minimal constraints on the key and value types:
//   K is the key type of each node.
//     K needs to be copy-able.
//   V is the type of data stored at each node.
//     V only needs to be move-able, and need not be copy-able.
//     Copy-ability is only needed when deep-copying the tree.
//   KeyComp is the comparator for K for ordering.
//     KeyComp can be a heterogenous lookup comparator (C++14).
//
// Key-value pairs are co-located together, and are iterator-stable, meaning
// that insertion/deletion operations do not invalidate existing iterators
// or existing pointers to other nodes in the same family tree.
// Insertion/deletion/search operations are O(lg N).
//
// Nodes maintain links to their parent (except the root node), so upwards
// navigation toward the root is always possible.
//
// Navigation:
//
//   MapTree (parent) <----------------.
//     |                                |
//     | .Find(key) -> iterator         |
//     |                                | .Parent() -> MapTree*
//     v  key_value_type (pair)         |
//   +=============+==================+ /
//   | .first:     | .second:         |/
//   |     key     |  MapTree (child) |
//   |   key_type  |  node_value_type |
//   +=============+==================+
//        ^                 |
//        |                 |
//         \---------------/
//              .Key() -> key_type*
//
// Example applications:
// * Dictionaries, where K is a single char.
// * Hierarchical symbol tables, where K is string-like.
//   * Lookup operations could use upward search.
// * Subcommand menus, where K is string-like.
// * File-system like structures, with string-like K.
//   * Navigation through parent directories uses upward links.
//
template <typename K, typename V, typename KeyComp = std::less<K>>
class MapTree {
  typedef MapTree<K, V, KeyComp> this_type;

  // Self-recursive type that holds subtrees.
  // A std::map is chosen for key-value co-location and iterator stability.
  // We chose std::map over std::set to allow values to be mutable, while keys
  // remain const.
  typedef std::map<K, this_type, KeyComp> subtrees_type;

 public:
  typedef K key_type;
  typedef V node_value_type;
  typedef typename subtrees_type::value_type key_value_type;  // pair
  typedef typename subtrees_type::iterator iterator;
  typedef typename subtrees_type::const_iterator const_iterator;

  MapTree() = default;

  // deep-copy, requires node_value_type to be copy-able.
  MapTree(const MapTree& other)
      : node_value_(other.node_value_),
        subtrees_(other.subtrees_),
        // new copy is disconnected from original parent and is a new root
        parent_(nullptr) {
    Relink();
  }

  // move (with relink)
  MapTree(MapTree&& other)
      : node_value_(std::move(other.node_value_)),
        subtrees_(std::move(other.subtrees_)),
        // Retain existing parent.
        parent_(other.parent_) {
    Relink();
  }

  // TODO(fangism): implement assignments as needed
  MapTree& operator=(const MapTree&) = delete;
  MapTree& operator=(MapTree&&) = delete;

  // Recursively initialize trees (copy node value).
  // Example:
  //   using M = MapTree<...>;
  //   using P = M::key_value_type;  // pair
  //   M tree(
  //     value0,
  //     P{key1, M(value1,
  //               P{key2, M(value2)},
  //               P{key3, M(value3)})},
  //     P{key4, M(value4,
  //               P{key5, M(value5)},
  //               P{key6, M(value6)})}
  //   );
  template <typename... Args>
  explicit MapTree(const node_value_type& v, Args&&... args)
      : node_value_(v), subtrees_() {
    EmplacePairs(std::forward<Args>(args)...);
  }

  // Recursively initialize trees (move node value).
  // See example above, using node_value_type copy.
  template <typename... Args>
  explicit MapTree(node_value_type&& v, Args&&... args)
      : node_value_(std::move(v)), subtrees_() {
    EmplacePairs(std::forward<Args>(args)...);
  }

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

  void swap(this_type& other) {
    std::swap(node_value_, other.node_value_);
    subtrees_.swap(other.subtrees_);
    Relink();
    other.Relink();
  }

  // Validation

  // Ensure parent-child mutual linkage invariant.
  // This property should hold after any mutating operation.
  bool CheckIntegrity() const {
    for (const auto& node : *this) {
      CHECK_EQ(node.second.Parent(), this)
          << "Inconsistency: child's parent does not point back to this node!";
      if (!node.second.CheckIntegrity()) return false;
    }
    return true;
  }

  // Insertion

  // Inserts a node at 'key' if it doesn't already exist.
  // 'args' are type V's constructor arguments, forwarded.
  // Returns (iterator, bool), where iterator points to the element at 'key'
  // whether or not it was newly inserted or already there, and true to indicate
  // that it was newly created, false if an entry already existed at that key.
  template <typename... Args>
  std::pair<iterator, bool> TryEmplace(const key_type& key, Args&&... args) {
    const auto p = subtrees_.emplace(
        key_value_type{key, node_value_type(std::forward<Args>(args)...)});
    if (p.second) {
      // Link child to parent.
      p.first->second.parent_ = this;
    }
    return p;
  }

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

  // Appends one or more sub-trees at this level.
  // Variadic template handles one argument at a time.
  // F and Args should each be key-value pairs (key_value_type).
  // If there are duplicate keys, only the first of each key will be taken,
  // while the other duplicates will be dropped.
  template <typename F, typename... Args>
  void EmplacePairs(F&& first, Args&&... args) {
    const auto p = subtrees_.emplace(std::forward<F>(first));
    if (p.second) {
      // Link child to parent.
      p.first->second.parent_ = this;
    }
    // Emplace the remaining items.
    EmplacePairs(std::forward<Args>(args)...);
  }

  // TODO(fangism): TryEmplaceHint(), like map::emplace_hint.

  // Erasure
  // TODO(fangism): void Erase(key);

  // Iteration/Navigation

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

  iterator begin() { return subtrees_.begin(); }
  const_iterator begin() const { return subtrees_.begin(); }
  iterator end() { return subtrees_.end(); }
  const_iterator end() const { return subtrees_.end(); }

  bool is_leaf() const { return Children().empty(); }

  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 HasAncestor(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 {
    const this_type* node = this;
    while (node->Parent() != nullptr) node = node->Parent();
    return node;
  }

  // Returns pointer to the key-value pair of which this node is the value.
  // Root nodes return nullptr because they have no associated key.
  const key_value_type* KeyValuePair() const {
    // Note: The use of offsetof below is technically undefined until C++17
    // because std::pair is not a standard layout type. However, all compilers
    // currently provide well-defined behavior as an extension (which is
    // demonstrated since constexpr evaluation must diagnose all undefined
    // behavior). However, GCC and Clang also warn about this use of offsetof,
    // which must be suppressed.
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
    // Compute offset of member &key_value_type::second (built-in function).
    static constexpr auto value_offset = offsetof(key_value_type, second);
    if (Parent() == nullptr) return nullptr;  // Root node has no key
    // All non-root nodes belong to a parent's map, and thus are
    // pair-co-located with a key.
    // Use pointer arithmetic to recover location of the key-value pair to which
    // this node value belongs.
    return reinterpret_cast<const key_value_type*>(
        reinterpret_cast<const char*>(this) - value_offset);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
    // TODO(fangism): factor this out into member_offsetof() template function.
  }

  // Returns the key associated with this node (if this is not a root),
  // otherwise return nullptr.
  const key_type* Key() const {
    if (Parent() == nullptr) return nullptr;  // Root node has no key
    return &KeyValuePair()->first;
  }

  // Access

  const subtrees_type& Children() const { return subtrees_; }

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

  // Search

  // Returns an iterator located at 'key' or end() if not found.
  // O(lg N), same as underlying map type.
  template <typename AnyKey>
  iterator Find(AnyKey&& key) {
    // Forward to underlying map::find, enabling heterogenous lookup.
    return subtrees_.find(std::forward<AnyKey>(key));
  }

  // Returns a const_iterator located at 'key' or end() if not found.
  // O(lg N), same as underlying map type.
  template <typename AnyKey>
  const_iterator Find(AnyKey&& key) const {
    // Forward to underlying map::find, enabling heterogenous lookup.
    return subtrees_.find(std::forward<AnyKey>(key));
  }

  // Traversals
  //
  // Function-application traversals' variants:
  //   * 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.
  // Note that keys can never be mutated.

  // Applies function 'f' to all nodes in this tree in a pre-order traversal.
  // Children are visited in key-order.
  void ApplyPreOrder(const std::function<void(const this_type&)>& f) const {
    f(*this);
    for (const auto& child : *this) {
      child.second.ApplyPreOrder(f);
    }
  }
  void ApplyPreOrder(const std::function<void(this_type&)>& f) {
    f(*this);
    for (auto& child : *this) {
      child.second.ApplyPreOrder(f);
    }
  }

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

  // Applies function 'f' to all nodes in this tree in a post-order traversal.
  // Children are visited in key-order.
  void ApplyPostOrder(const std::function<void(const this_type&)>& f) const {
    for (const auto& child : *this) {
      child.second.ApplyPostOrder(f);
    }
    f(*this);
  }
  void ApplyPostOrder(const std::function<void(this_type&)>& f) {
    for (auto& child : *this) {
      child.second.ApplyPostOrder(f);
    }
    f(*this);
  }

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

  // Transforms

  // Printing and formatting

  // Pretty-print tree, using a custom node_value printer function.
  // Keys are printed using operator<<.
  std::ostream& PrintTree(
      std::ostream& stream,
      const std::function<std::ostream&(std::ostream&, const node_value_type&,
                                        size_t value_indent)>& printer,
      size_t indent = 0) const {
    // Indentation will be printed before the key, not here.
    printer(stream << "{ (", Value(), indent) << ')';
    if (Children().empty()) {
      stream << " }";
    } else {
      stream << '\n';
      for (const auto& child : Children()) {
        stream << Spacer(indent + 2) << child.first << ": ";
        child.second.PrintTree(stream, printer, indent + 2) << '\n';
      }
      stream << Spacer(indent) << '}';
    }
    return stream;
  }

  // Pretty-print tree, using the default stream printer, which requires that
  // operator<<(std::ostream&, const node_value_type&) is defined.
  std::ostream& PrintTree(std::ostream& stream, size_t indent = 0) const {
    return PrintTree(
        stream,
        [](std::ostream& s, const node_value_type& v,
           size_t unused_indent) -> std::ostream& { return s << v; },
        indent);
  }

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

 private:  // data
  // Singular value stored at this node.
  node_value_type node_value_;

  // Collection of subtrees
  subtrees_type subtrees_;

  // Pointer to parent node, or nullptr if this is a root node.
  this_type* parent_ = nullptr;
};

}  // namespace verible

#endif  // VERIBLE_COMMON_UTIL_MAP_TREE_H_
