/* -*-  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 NDN_CONTENT_STORE_IMPL_H_
#define NDN_CONTENT_STORE_IMPL_H_

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

#include "ndn-content-store.hpp"

#include "ns3/packet.h"
#include <boost/foreach.hpp>

#include "ns3/log.h"
#include "ns3/uinteger.h"
#include "ns3/string.h"

#include "../../utils/trie/trie-with-policy.hpp"

namespace ns3 {
namespace ndn {
namespace cs {

/**
 * @ingroup ndn-cs
 * @brief Cache entry implementation with additional references to the base container
 */
template<class CS>
class EntryImpl : public Entry {
public:
  typedef Entry base_type;

public:
  EntryImpl(Ptr<ContentStore> cs, shared_ptr<const Data> data)
    : Entry(cs, data)
    , item_(0)
  {
  }

  void
  SetTrie(typename CS::super::iterator item)
  {
    item_ = item;
  }

  typename CS::super::iterator
  to_iterator()
  {
    return item_;
  }
  typename CS::super::const_iterator
  to_iterator() const
  {
    return item_;
  }

private:
  typename CS::super::iterator item_;
};

/**
 * @ingroup ndn-cs
 * @brief Base implementation of NDN content store
 */
template<class Policy>
class ContentStoreImpl
  : public ContentStore,
    protected ndnSIM::
      trie_with_policy<Name,
                       ndnSIM::smart_pointer_payload_traits<EntryImpl<ContentStoreImpl<Policy>>,
                                                            Entry>,
                       Policy> {
public:
  typedef ndnSIM::
    trie_with_policy<Name, ndnSIM::smart_pointer_payload_traits<EntryImpl<ContentStoreImpl<Policy>>,
                                                                Entry>,
                     Policy> super;

  typedef EntryImpl<ContentStoreImpl<Policy>> entry;

  static TypeId
  GetTypeId();

  ContentStoreImpl(){};
  virtual ~ContentStoreImpl(){};

  // from ContentStore

  virtual inline shared_ptr<Data>
  Lookup(shared_ptr<const Interest> interest);

  virtual inline bool
  Add(shared_ptr<const Data> data);

  // virtual bool
  // Remove (shared_ptr<Interest> header);

  virtual inline void
  Print(std::ostream& os) const;

  virtual uint32_t
  GetSize() const;

  virtual Ptr<Entry>
  Begin();

  virtual Ptr<Entry>
  End();

  virtual Ptr<Entry> Next(Ptr<Entry>);

  const typename super::policy_container&
  GetPolicy() const
  {
    return super::getPolicy();
  }

  typename super::policy_container&
  GetPolicy()
  {
    return super::getPolicy();
  }

private:
  void
  SetMaxSize(uint32_t maxSize);

  uint32_t
  GetMaxSize() const;

private:
  static LogComponent g_log; ///< @brief Logging variable

  /// @brief trace of for entry additions (fired every time entry is successfully added to the
  /// cache): first parameter is pointer to the CS entry
  TracedCallback<Ptr<const Entry>> m_didAddEntry;
};

//////////////////////////////////////////
////////// Implementation ////////////////
//////////////////////////////////////////

template<class Policy>
LogComponent
  ContentStoreImpl<Policy>::g_log = LogComponent(("ndn.cs." + Policy::GetName()).c_str());

template<class Policy>
TypeId
ContentStoreImpl<Policy>::GetTypeId()
{
  static TypeId tid =
    TypeId(("ns3::ndn::cs::" + Policy::GetName()).c_str())
      .SetGroupName("Ndn")
      .SetParent<ContentStore>()
      .AddConstructor<ContentStoreImpl<Policy>>()
      .AddAttribute("MaxSize",
                    "Set maximum number of entries in ContentStore. If 0, limit is not enforced",
                    StringValue("100"), MakeUintegerAccessor(&ContentStoreImpl<Policy>::GetMaxSize,
                                                             &ContentStoreImpl<Policy>::SetMaxSize),
                    MakeUintegerChecker<uint32_t>())

      .AddTraceSource("DidAddEntry",
                      "Trace fired every time entry is successfully added to the cache",
                      MakeTraceSourceAccessor(&ContentStoreImpl<Policy>::m_didAddEntry));

  return tid;
}

struct isNotExcluded {
  inline isNotExcluded(const Exclude& exclude)
    : m_exclude(exclude)
  {
  }

  bool
  operator()(const name::Component& comp) const
  {
    return !m_exclude.isExcluded(comp);
  }

private:
  const Exclude& m_exclude;
};

template<class Policy>
shared_ptr<Data>
ContentStoreImpl<Policy>::Lookup(shared_ptr<const Interest> interest)
{
  NS_LOG_FUNCTION(this << interest->GetName());

  typename super::const_iterator node;
  if (interest->GetExclude() == 0) {
    node = this->deepest_prefix_match(interest->GetName());
  }
  else {
    node = this->deepest_prefix_match_if_next_level(interest->GetName(),
                                                    isNotExcluded(*interest->GetExclude()));
  }

  if (node != this->end()) {
    this->m_cacheHitsTrace(interest, node->payload()->GetData());

    shared_ptr<Data> copy = make_shared<Data>(*node->payload()->GetData());
    ConstCast<Packet>(copy->GetPayload())->RemoveAllPacketTags();
    return copy;
  }
  else {
    this->m_cacheMissesTrace(interest);
    return 0;
  }
}

template<class Policy>
bool
ContentStoreImpl<Policy>::Add(shared_ptr<const Data> data)
{
  NS_LOG_FUNCTION(this << data->GetName());

  Ptr<entry> newEntry = Create<entry>(this, data);
  std::pair<typename super::iterator, bool> result = super::insert(data->GetName(), newEntry);

  if (result.first != super::end()) {
    if (result.second) {
      newEntry->SetTrie(result.first);

      m_didAddEntry(newEntry);
      return true;
    }
    else {
      // should we do anything?
      // update payload? add new payload?
      return false;
    }
  }
  else
    return false; // cannot insert entry
}

template<class Policy>
void
ContentStoreImpl<Policy>::Print(std::ostream& os) const
{
  for (typename super::policy_container::const_iterator item = this->getPolicy().begin();
       item != this->getPolicy().end(); item++) {
    os << item->payload()->GetName() << std::endl;
  }
}

template<class Policy>
void
ContentStoreImpl<Policy>::SetMaxSize(uint32_t maxSize)
{
  this->getPolicy().set_max_size(maxSize);
}

template<class Policy>
uint32_t
ContentStoreImpl<Policy>::GetMaxSize() const
{
  return this->getPolicy().get_max_size();
}

template<class Policy>
uint32_t
ContentStoreImpl<Policy>::GetSize() const
{
  return this->getPolicy().size();
}

template<class Policy>
Ptr<Entry>
ContentStoreImpl<Policy>::Begin()
{
  typename super::parent_trie::recursive_iterator item(super::getTrie()), end(0);
  for (; item != end; item++) {
    if (item->payload() == 0)
      continue;
    break;
  }

  if (item == end)
    return End();
  else
    return item->payload();
}

template<class Policy>
Ptr<Entry>
ContentStoreImpl<Policy>::End()
{
  return 0;
}

template<class Policy>
Ptr<Entry>
ContentStoreImpl<Policy>::Next(Ptr<Entry> from)
{
  if (from == 0)
    return 0;

  typename super::parent_trie::recursive_iterator item(*StaticCast<entry>(from)->to_iterator()),
    end(0);

  for (item++; item != end; item++) {
    if (item->payload() == 0)
      continue;
    break;
  }

  if (item == end)
    return End();
  else
    return item->payload();
}

} // namespace cs
} // namespace ndn
} // namespace ns3

#endif // NDN_CONTENT_STORE_IMPL_H_
