/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2011-2015  Regents of the University of California.
 *
 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
 * contributors.
 *
 * ndnSIM is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * ndnSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#ifndef TRIE_H_
#define TRIE_H_

/// @cond include_hidden

#include "ns3/ndnSIM/model/ndn-common.hpp"

#include "ns3/ptr.h"

#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/functional/hash.hpp>
#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
#include <tuple>
#include <boost/foreach.hpp>
#include <boost/mpl/if.hpp>

namespace ns3 {
namespace ndn {
namespace ndnSIM {

/////////////////////////////////////////////////////
// Allow customization for payload
//
template<typename Payload, typename BasePayload = Payload>
struct pointer_payload_traits {
  typedef Payload payload_type;  // general type of the payload
  typedef Payload* storage_type; // how the payload is actually stored
  typedef Payload* insert_type;  // what parameter is inserted

  typedef Payload* return_type;             // what is returned on access
  typedef const Payload* const_return_type; // what is returned on const access

  typedef BasePayload*
    base_type; // base type of the entry (when implementation details need to be hidden)
  typedef const BasePayload*
    const_base_type; // const base type of the entry (when implementation details need to be hidden)

  static Payload* empty_payload;
};

template<typename Payload, typename BasePayload>
Payload* pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;

template<typename Payload, typename BasePayload = Payload>
struct smart_pointer_payload_traits {
  typedef Payload payload_type;
  typedef ns3::Ptr<Payload> storage_type;
  typedef ns3::Ptr<Payload> insert_type;

  typedef ns3::Ptr<Payload> return_type;
  typedef ns3::Ptr<const Payload> const_return_type;

  typedef ns3::Ptr<BasePayload> base_type;
  typedef ns3::Ptr<const BasePayload> const_base_type;

  static ns3::Ptr<Payload> empty_payload;
};

template<typename Payload, typename BasePayload>
ns3::Ptr<Payload> smart_pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;

template<typename Payload, typename BasePayload = Payload>
struct non_pointer_traits {
  typedef Payload payload_type;
  typedef Payload storage_type;
  typedef const Payload& insert_type; // nothing to insert

  typedef Payload& return_type;
  typedef const Payload& const_return_type;

  typedef BasePayload& base_type;
  typedef const BasePayload& const_base_type;

  static Payload empty_payload;
};

template<typename Payload, typename BasePayload>
Payload non_pointer_traits<Payload, BasePayload>::empty_payload = Payload();

////////////////////////////////////////////////////
// forward declarations
//
template<typename FullKey, typename PayloadTraits, typename PolicyHook>
class trie;

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
inline std::ostream&
operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
bool
operator==(const trie<FullKey, PayloadTraits, PolicyHook>& a,
           const trie<FullKey, PayloadTraits, PolicyHook>& b);

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
std::size_t
hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);

///////////////////////////////////////////////////
// actual definition
//
template<class T, class NonConstT>
class trie_iterator;

template<class T>
class trie_point_iterator;

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
class trie {
public:
  typedef typename FullKey::value_type Key;

  typedef trie* iterator;
  typedef const trie* const_iterator;

  typedef trie_iterator<trie, trie> recursive_iterator;
  typedef trie_iterator<const trie, trie> const_recursive_iterator;

  typedef trie_point_iterator<trie> point_iterator;
  typedef trie_point_iterator<const trie> const_point_iterator;

  typedef PayloadTraits payload_traits;

  inline trie(const Key& key, size_t bucketSize = 1, size_t bucketIncrement = 1)
    : key_(key)
    , initialBucketSize_(bucketSize)
    , bucketIncrement_(bucketIncrement)
    , bucketSize_(initialBucketSize_)
    , buckets_(new bucket_type[bucketSize_]) // cannot use normal pointer, because lifetime of
                                             // buckets should be larger than lifetime of the
                                             // container
    , children_(bucket_traits(buckets_.get(), bucketSize_))
    , payload_(PayloadTraits::empty_payload)
    , parent_(nullptr)
  {
  }

  inline ~trie()
  {
    payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
    children_.clear_and_dispose(trie_delete_disposer());
  }

  void
  clear()
  {
    children_.clear_and_dispose(trie_delete_disposer());
  }

  template<class Predicate>
  void
  clear_if(Predicate cond)
  {
    recursive_iterator trieNode(this);
    recursive_iterator end(0);

    while (trieNode != end) {
      if (cond(*trieNode)) {
        trieNode = recursive_iterator(trieNode->erase());
      }
      trieNode++;
    }
  }

  // actual entry
  friend bool operator==<>(const trie<FullKey, PayloadTraits, PolicyHook>& a,
                           const trie<FullKey, PayloadTraits, PolicyHook>& b);

  friend std::size_t
  hash_value<>(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);

  inline std::pair<iterator, bool>
  insert(const FullKey& key, typename PayloadTraits::insert_type payload)
  {
    trie* trieNode = this;

    BOOST_FOREACH (const Key& subkey, key) {
      typename unordered_set::iterator item = trieNode->children_.find(subkey);
      if (item == trieNode->children_.end()) {
        trie* newNode = new trie(subkey, initialBucketSize_, bucketIncrement_);
        // std::cout << "new " << newNode << "\n";
        newNode->parent_ = trieNode;

        if (trieNode->children_.size() >= trieNode->bucketSize_) {
          trieNode->bucketSize_ += trieNode->bucketIncrement_;
          trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially

          buckets_array newBuckets(new bucket_type[trieNode->bucketSize_]);
          trieNode->children_.rehash(bucket_traits(newBuckets.get(), trieNode->bucketSize_));
          trieNode->buckets_.swap(newBuckets);
        }

        std::pair<typename unordered_set::iterator, bool> ret =
          trieNode->children_.insert(*newNode);

        trieNode = &(*ret.first);
      }
      else
        trieNode = &(*item);
    }

    if (trieNode->payload_ == PayloadTraits::empty_payload) {
      trieNode->payload_ = payload;
      return std::make_pair(trieNode, true);
    }
    else
      return std::make_pair(trieNode, false);
  }

  /**
   * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
   */
  inline iterator
  erase()
  {
    payload_ = PayloadTraits::empty_payload;
    return prune();
  }

  /**
   * @brief Do exactly as erase, but without erasing the payload
   */
  inline iterator
  prune()
  {
    if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) {
      if (parent_ == 0)
        return this;

      trie* parent = parent_;
      parent->children_
        .erase_and_dispose(*this,
                           trie_delete_disposer()); // delete this; basically, committing a suicide

      return parent->prune();
    }
    return this;
  }

  /**
   * @brief Perform prune of the node, but without attempting to parent of the node
   */
  inline void
  prune_node()
  {
    if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) {
      if (parent_ == 0)
        return;

      trie* parent = parent_;
      parent->children_
        .erase_and_dispose(*this,
                           trie_delete_disposer()); // delete this; basically, committing a suicide
    }
  }

  // inline std::tuple<const iterator, bool, const iterator>
  // find (const FullKey &key) const
  // {
  //   return const_cast<trie*> (this)->find (key);
  // }

  /**
   * @brief Perform the longest prefix match
   * @param key the key for which to perform the longest prefix match
   *
   * @return ->second is true if prefix in ->first is longer than key
   */
  inline std::tuple<iterator, bool, iterator>
  find(const FullKey& key)
  {
    trie* trieNode = this;
    iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
    bool reachLast = true;

    BOOST_FOREACH (const Key& subkey, key) {
      typename unordered_set::iterator item = trieNode->children_.find(subkey);
      if (item == trieNode->children_.end()) {
        reachLast = false;
        break;
      }
      else {
        trieNode = &(*item);

        if (trieNode->payload_ != PayloadTraits::empty_payload)
          foundNode = trieNode;
      }
    }

    return std::make_tuple(foundNode, reachLast, trieNode);
  }

  /**
   * @brief Perform the longest prefix match satisfying preficate
   * @param key the key for which to perform the longest prefix match
   *
   * @return ->second is true if prefix in ->first is longer than key
   */
  template<class Predicate>
  inline std::tuple<iterator, bool, iterator>
  find_if(const FullKey& key, Predicate pred)
  {
    trie* trieNode = this;
    iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
    bool reachLast = true;

    BOOST_FOREACH (const Key& subkey, key) {
      typename unordered_set::iterator item = trieNode->children_.find(subkey);
      if (item == trieNode->children_.end()) {
        reachLast = false;
        break;
      }
      else {
        trieNode = &(*item);

        if (trieNode->payload_ != PayloadTraits::empty_payload && pred(trieNode->payload_)) {
          foundNode = trieNode;
        }
      }
    }

    return std::make_tuple(foundNode, reachLast, trieNode);
  }

  /**
   * @brief Find next payload of the sub-trie
   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
   * )
   */
  inline iterator
  find()
  {
    if (payload_ != PayloadTraits::empty_payload)
      return this;

    typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
    for (typename trie::unordered_set::iterator subnode = children_.begin();
         subnode != children_.end(); subnode++)
    // BOOST_FOREACH (trie &subnode, children_)
    {
      iterator value = subnode->find();
      if (value != 0)
        return value;
    }

    return 0;
  }

  /**
   * @brief Find next payload of the sub-trie satisfying the predicate
   * @param pred predicate
   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
   * )
   */
  template<class Predicate>
  inline const iterator
  find_if(Predicate pred)
  {
    if (payload_ != PayloadTraits::empty_payload && pred(payload_))
      return this;

    typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
    for (typename trie::unordered_set::iterator subnode = children_.begin();
         subnode != children_.end(); subnode++)
    // BOOST_FOREACH (const trie &subnode, children_)
    {
      iterator value = subnode->find_if(pred);
      if (value != 0)
        return value;
    }

    return 0;
  }

  /**
   * @brief Find next payload of the sub-trie satisfying the predicate
   * @param pred predicate
   *
   * This version check predicate only for the next level children
   *
   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
   *)
   */
  template<class Predicate>
  inline const iterator
  find_if_next_level(Predicate pred)
  {
    typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
    for (typename trie::unordered_set::iterator subnode = children_.begin();
         subnode != children_.end(); subnode++) {
      if (pred(subnode->key())) {
        return subnode->find();
      }
    }

    return 0;
  }

  iterator
  end()
  {
    return 0;
  }

  const_iterator
  end() const
  {
    return 0;
  }

  typename PayloadTraits::const_return_type
  payload() const
  {
    return payload_;
  }

  typename PayloadTraits::return_type
  payload()
  {
    return payload_;
  }

  void
  set_payload(typename PayloadTraits::insert_type payload)
  {
    payload_ = payload;
  }

  Key
  key() const
  {
    return key_;
  }

  inline void
  PrintStat(std::ostream& os) const;

private:
  // The disposer object function
  struct trie_delete_disposer {
    void
    operator()(trie* delete_this)
    {
      delete delete_this;
    }
  };

  template<class D>
  struct array_disposer {
    void
    operator()(D* array)
    {
      delete[] array;
    }
  };

  friend std::ostream& operator<<<>(std::ostream& os, const trie& trie_node);

public:
  PolicyHook policy_hook_;

private:
  boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;

  // necessary typedefs
  typedef trie self_type;
  typedef boost::intrusive::member_hook<trie, boost::intrusive::unordered_set_member_hook<>,
                                        &trie::unordered_set_member_hook_> member_hook;

  typedef boost::intrusive::unordered_set<trie, member_hook> unordered_set;
  typedef typename unordered_set::bucket_type bucket_type;
  typedef typename unordered_set::bucket_traits bucket_traits;

  template<class T, class NonConstT>
  friend class trie_iterator;

  template<class T>
  friend class trie_point_iterator;

  ////////////////////////////////////////////////
  // Actual data
  ////////////////////////////////////////////////

  Key key_; ///< name component

  size_t initialBucketSize_;
  size_t bucketIncrement_;

  size_t bucketSize_;
  typedef boost::interprocess::unique_ptr<bucket_type, array_disposer<bucket_type>> buckets_array;
  buckets_array buckets_;
  unordered_set children_;

  typename PayloadTraits::storage_type payload_;
  trie* parent_; // to make cleaning effective
};

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
inline std::ostream&
operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node)
{
  os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "")
     << std::endl;
  typedef trie<FullKey, PayloadTraits, PolicyHook> trie;

  for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin();
       subnode != trie_node.children_.end(); subnode++)
  // BOOST_FOREACH (const trie &subnode, trie_node.children_)
  {
    os << "\"" << &trie_node << "\""
       << " [label=\"" << trie_node.key_
       << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]\n";
    os << "\"" << &(*subnode) << "\""
       << " [label=\"" << subnode->key_
       << ((subnode->payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]"
                                                                              "\n";

    os << "\"" << &trie_node << "\""
       << " -> "
       << "\"" << &(*subnode) << "\""
       << "\n";
    os << *subnode;
  }

  return os;
}

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
inline void
trie<FullKey, PayloadTraits, PolicyHook>::PrintStat(std::ostream& os) const
{
  os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload) ? "*" : "") << ": "
     << children_.size() << " children" << std::endl;
  for (size_t bucket = 0, maxbucket = children_.bucket_count(); bucket < maxbucket; bucket++) {
    os << " " << children_.bucket_size(bucket);
  }
  os << "\n";

  typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
  for (typename trie::unordered_set::const_iterator subnode = children_.begin();
       subnode != children_.end(); subnode++)
  // BOOST_FOREACH (const trie &subnode, children_)
  {
    subnode->PrintStat(os);
  }
}

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
inline bool
operator==(const trie<FullKey, PayloadTraits, PolicyHook>& a,
           const trie<FullKey, PayloadTraits, PolicyHook>& b)
{
  return a.key_ == b.key_;
}

template<typename FullKey, typename PayloadTraits, typename PolicyHook>
inline std::size_t
hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node)
{
  return boost::hash_value(trie_node.key_);
}

template<class Trie, class NonConstTrie> // hack for boost < 1.47
class trie_iterator {
public:
  trie_iterator()
    : trie_(0)
  {
  }
  trie_iterator(typename Trie::iterator item)
    : trie_(item)
  {
  }
  trie_iterator(Trie& item)
    : trie_(&item)
  {
  }

  Trie& operator*()
  {
    return *trie_;
  }
  const Trie& operator*() const
  {
    return *trie_;
  }
  Trie* operator->()
  {
    return trie_;
  }
  const Trie* operator->() const
  {
    return trie_;
  }
  bool
  operator==(trie_iterator<const Trie, NonConstTrie>& other) const
  {
    return (trie_ == other.trie_);
  }
  bool
  operator==(trie_iterator<Trie, NonConstTrie>& other)
  {
    return (trie_ == other.trie_);
  }
  bool
  operator!=(trie_iterator<const Trie, NonConstTrie>& other) const
  {
    return !(*this == other);
  }
  bool
  operator!=(trie_iterator<Trie, NonConstTrie>& other)
  {
    return !(*this == other);
  }

  trie_iterator<Trie, NonConstTrie>&
  operator++(int)
  {
    if (trie_->children_.size() > 0)
      trie_ = &(*trie_->children_.begin());
    else
      trie_ = goUp();
    return *this;
  }

  trie_iterator<Trie, NonConstTrie>&
  operator++()
  {
    (*this)++;
    return *this;
  }

private:
  typedef typename boost::mpl::if_<boost::is_same<Trie, NonConstTrie>,
                                   typename Trie::unordered_set::iterator,
                                   typename Trie::unordered_set::const_iterator>::type set_iterator;

  Trie*
  goUp()
  {
    if (trie_->parent_ != 0) {
      // typename Trie::unordered_set::iterator item =
      set_iterator item = const_cast<NonConstTrie*>(trie_)
                            ->parent_->children_.iterator_to(const_cast<NonConstTrie&>(*trie_));
      item++;
      if (item != trie_->parent_->children_.end()) {
        return &(*item);
      }
      else {
        trie_ = trie_->parent_;
        return goUp();
      }
    }
    else
      return 0;
  }

private:
  Trie* trie_;
};

template<class Trie>
class trie_point_iterator {
private:
  typedef typename boost::mpl::if_<boost::is_same<Trie, const Trie>,
                                   typename Trie::unordered_set::const_iterator,
                                   typename Trie::unordered_set::iterator>::type set_iterator;

public:
  trie_point_iterator()
    : trie_(0)
  {
  }
  trie_point_iterator(typename Trie::iterator item)
    : trie_(item)
  {
  }
  trie_point_iterator(Trie& item)
  {
    if (item.children_.size() != 0)
      trie_ = &*item.children_.begin();
    else
      trie_ = 0;
  }

  Trie& operator*()
  {
    return *trie_;
  }
  const Trie& operator*() const
  {
    return *trie_;
  }
  Trie* operator->()
  {
    return trie_;
  }
  const Trie* operator->() const
  {
    return trie_;
  }
  bool
  operator==(trie_point_iterator<const Trie>& other) const
  {
    return (trie_ == other.trie_);
  }
  bool
  operator==(trie_point_iterator<Trie>& other)
  {
    return (trie_ == other.trie_);
  }
  bool
  operator!=(trie_point_iterator<const Trie>& other) const
  {
    return !(*this == other);
  }
  bool
  operator!=(trie_point_iterator<Trie>& other)
  {
    return !(*this == other);
  }

  trie_point_iterator<Trie>&
  operator++(int)
  {
    if (trie_->parent_ != 0) {
      set_iterator item = trie_->parent_->children_.iterator_to(*trie_);
      item++;
      if (item == trie_->parent_->children_.end())
        trie_ = 0;
      else
        trie_ = &*item;
    }
    else {
      trie_ = 0;
    }
    return *this;
  }

  trie_point_iterator<Trie>&
  operator++()
  {
    (*this)++;
    return *this;
  }

private:
  Trie* trie_;
};

} // ndnSIM
} // ndn
} // ns3

/// @endcond

#endif // TRIE_H_
