/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2011 University of California, Los Angeles
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 */

#ifndef TRIE_H_
#define TRIE_H_

#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 <boost/tuple/tuple.hpp>
#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::partial_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_ (0)
  {
  }

  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 boost::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 boost::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 boost::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 boost::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 boost::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

#endif // TRIE_H_
