/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "in-memory-storage.hpp"
#include "in-memory-storage-entry.hpp"

#include "../security/signature-sha256-with-rsa.hpp"

namespace ndn {
namespace util {

const time::milliseconds InMemoryStorage::INFINITE_WINDOW(-1);
const time::milliseconds InMemoryStorage::ZERO_WINDOW(0);

InMemoryStorage::const_iterator::const_iterator(const Data* ptr, const Cache* cache,
                                                Cache::index<byFullName>::type::iterator it)
  : m_ptr(ptr)
  , m_cache(cache)
  , m_it(it)
{
}

InMemoryStorage::const_iterator&
InMemoryStorage::const_iterator::operator++()
{
  m_it++;
  if (m_it != m_cache->get<byFullName>().end()) {
    m_ptr = &((*m_it)->getData());
  }
  else {
    m_ptr = 0;
  }

  return *this;
}

InMemoryStorage::const_iterator
InMemoryStorage::const_iterator::operator++(int)
{
  InMemoryStorage::const_iterator i(*this);
  this->operator++();
  return i;
}

const Data&
InMemoryStorage::const_iterator::operator*()
{
  return *m_ptr;
}

const Data*
InMemoryStorage::const_iterator::operator->()
{
  return m_ptr;
}

bool
InMemoryStorage::const_iterator::operator==(const const_iterator& rhs)
{
  return m_it == rhs.m_it;
}

bool
InMemoryStorage::const_iterator::operator!=(const const_iterator& rhs)
{
  return m_it != rhs.m_it;
}

InMemoryStorage::InMemoryStorage(size_t limit)
  : m_limit(limit)
  , m_nPackets(0)
{
  init();
}

InMemoryStorage::InMemoryStorage(boost::asio::io_service& ioService, size_t limit)
  : m_limit(limit)
  , m_nPackets(0)
{
  m_scheduler = make_unique<Scheduler>(ioService);
  init();
}

void
InMemoryStorage::init()
{
  // TODO consider a more suitable initial value
  m_capacity = 10;

  if (m_limit != std::numeric_limits<size_t>::max() && m_capacity > m_limit) {
    m_capacity = m_limit;
  }

  for (size_t i = 0; i < m_capacity; i++) {
    m_freeEntries.push(new InMemoryStorageEntry());
  }
}

InMemoryStorage::~InMemoryStorage()
{
  // evict all items from cache
  Cache::iterator it = m_cache.begin();
  while (it != m_cache.end()) {
    it = freeEntry(it);
  }

  BOOST_ASSERT(m_freeEntries.size() == m_capacity);

  while (!m_freeEntries.empty()) {
    delete m_freeEntries.top();
    m_freeEntries.pop();
  }
}

void
InMemoryStorage::setCapacity(size_t capacity)
{
  size_t oldCapacity = m_capacity;
  m_capacity = capacity;

  if (size() > m_capacity) {
    ssize_t nAllowedFailures = size() - m_capacity;
    while (size() > m_capacity) {
      if (!evictItem() && --nAllowedFailures < 0) {
        BOOST_THROW_EXCEPTION(Error());
      }
    }
  }

  if (m_capacity >= oldCapacity) {
    for (size_t i = oldCapacity; i < m_capacity; i++) {
      m_freeEntries.push(new InMemoryStorageEntry());
    }
  }
  else {
    for (size_t i = oldCapacity; i > m_capacity; i--) {
      delete m_freeEntries.top();
      m_freeEntries.pop();
    }
  }

  BOOST_ASSERT(size() + m_freeEntries.size() == m_capacity);
}

void
InMemoryStorage::insert(const Data& data, const time::milliseconds& mustBeFreshProcessingWindow)
{
  //check if identical Data/Name already exists
  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().find(data.getFullName());
  if (it != m_cache.get<byFullName>().end())
    return;

  //if full, double the capacity
  bool doesReachLimit = (getLimit() == getCapacity());
  if (isFull() && !doesReachLimit) {
    // note: This is incorrect if 2*capacity overflows, but memory should run out before that
    size_t newCapacity = std::min(2 * getCapacity(), getLimit());
    setCapacity(newCapacity);
  }

  //if full and reach limitation of the capacity, employ replacement policy
  if (isFull() && doesReachLimit) {
    evictItem();
  }

  //insert to cache
  BOOST_ASSERT(m_freeEntries.size() > 0);
  // take entry for the memory pool
  InMemoryStorageEntry* entry = m_freeEntries.top();
  m_freeEntries.pop();
  m_nPackets++;
  entry->setData(data);
  if (m_scheduler != nullptr && mustBeFreshProcessingWindow > ZERO_WINDOW) {
    auto eventId = make_unique<scheduler::ScopedEventId>(*m_scheduler);
    *eventId = m_scheduler->scheduleEvent(mustBeFreshProcessingWindow,
                                          bind(&InMemoryStorageEntry::markStale, entry));
    entry->setMarkStaleEventId(std::move(eventId));
  }
  m_cache.insert(entry);

  //let derived class do something with the entry
  afterInsert(entry);
}

shared_ptr<const Data>
InMemoryStorage::find(const Name& name)
{
  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().lower_bound(name);

  //if not found, return null
  if (it == m_cache.get<byFullName>().end()) {
    return shared_ptr<const Data>();
  }

  //if the given name is not the prefix of the lower_bound, return null
  if (!name.isPrefixOf((*it)->getFullName())) {
    return shared_ptr<const Data>();
  }

  afterAccess(*it);
  return ((*it)->getData()).shared_from_this();
}

shared_ptr<const Data>
InMemoryStorage::find(const Interest& interest)
{
  //if the interest contains implicit digest, it is possible to directly locate a packet.
  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>()
                                                    .find(interest.getName());

  //if a packet is located by its full name, it must be the packet to return.
  if (it != m_cache.get<byFullName>().end()) {
    return ((*it)->getData()).shared_from_this();
  }

  //if the packet is not discovered by last step, either the packet is not in the storage or
  //the interest doesn't contains implicit digest.
  it = m_cache.get<byFullName>().lower_bound(interest.getName());

  if (it == m_cache.get<byFullName>().end()) {
    return shared_ptr<const Data>();
  }

  //to locate the element that has a just smaller name than the interest's
  if (it != m_cache.get<byFullName>().begin())
    it--;

  InMemoryStorageEntry* ret = selectChild(interest, it);
  if (ret != 0) {
    //let derived class do something with the entry
    afterAccess(ret);
    return ret->getData().shared_from_this();
  }
  else {
    return shared_ptr<const Data>();
  }
}

InMemoryStorage::Cache::index<InMemoryStorage::byFullName>::type::iterator
InMemoryStorage::findNextFresh(Cache::index<byFullName>::type::iterator it) const
{
  for (; it != m_cache.get<byFullName>().end(); it++) {
    if ((*it)->isFresh())
      return it;
  }

  return it;
}

InMemoryStorageEntry*
InMemoryStorage::selectChild(const Interest& interest,
                             Cache::index<byFullName>::type::iterator startingPoint) const
{
  BOOST_ASSERT(startingPoint != m_cache.get<byFullName>().end());

  if (startingPoint != m_cache.get<byFullName>().begin())
    {
      BOOST_ASSERT((*startingPoint)->getFullName() < interest.getName());
    }

  bool hasLeftmostSelector = (interest.getChildSelector() <= 0);
  bool hasRightmostSelector = !hasLeftmostSelector;

  // filter out "stale" data
  if (interest.getMustBeFresh())
    startingPoint = findNextFresh(startingPoint);

  if (startingPoint == m_cache.get<byFullName>().end()) {
    return nullptr;
  }

  if (hasLeftmostSelector)
    {
      if (interest.matchesData((*startingPoint)->getData()))
        {
          return *startingPoint;
        }
    }

  //iterate to the right
  Cache::index<byFullName>::type::iterator rightmost = startingPoint;
  if (startingPoint != m_cache.get<byFullName>().end())
    {
      Cache::index<byFullName>::type::iterator rightmostCandidate = startingPoint;
      Name currentChildPrefix("");

      while (true)
        {
          ++rightmostCandidate;
          // filter out "stale" data
          if (interest.getMustBeFresh())
            rightmostCandidate = findNextFresh(rightmostCandidate);

          bool isInBoundaries = (rightmostCandidate != m_cache.get<byFullName>().end());
          bool isInPrefix = false;
          if (isInBoundaries)
            {
              isInPrefix = interest.getName().isPrefixOf((*rightmostCandidate)->getFullName());
            }

          if (isInPrefix)
            {
              if (interest.matchesData((*rightmostCandidate)->getData()))
                {
                  if (hasLeftmostSelector)
                    {
                      return *rightmostCandidate;
                    }

                  if (hasRightmostSelector)
                    {
                      // get prefix which is one component longer than Interest name
                      const Name& childPrefix = (*rightmostCandidate)->getFullName()
                                                  .getPrefix(interest.getName().size() + 1);

                      if (currentChildPrefix.empty() || (childPrefix != currentChildPrefix))
                        {
                          currentChildPrefix = childPrefix;
                          rightmost = rightmostCandidate;
                        }
                    }
                }
            }
          else
            break;
        }
    }

  if (rightmost != startingPoint)
    {
      return *rightmost;
    }

  if (hasRightmostSelector) // if rightmost was not found, try starting point
    {
      if (interest.matchesData((*startingPoint)->getData()))
        {
          return *startingPoint;
        }
    }

  return 0;
}

InMemoryStorage::Cache::iterator
InMemoryStorage::freeEntry(Cache::iterator it)
{
  //push the *empty* entry into mem pool
  (*it)->release();
  m_freeEntries.push(*it);
  m_nPackets--;
  return m_cache.erase(it);
}

void
InMemoryStorage::erase(const Name& prefix, const bool isPrefix)
{
  if (isPrefix) {
    Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().lower_bound(prefix);

    while (it != m_cache.get<byFullName>().end() && prefix.isPrefixOf((*it)->getName())) {
      //let derived class do something with the entry
      beforeErase(*it);
      it = freeEntry(it);
    }
  }
  else {
    Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().find(prefix);

    if (it == m_cache.get<byFullName>().end())
      return;

    //let derived class do something with the entry
    beforeErase(*it);
    freeEntry(it);
  }

  if (m_freeEntries.size() > (2 * size()))
    setCapacity(getCapacity() / 2);
}

void
InMemoryStorage::eraseImpl(const Name& name)
{
  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().find(name);

  if (it == m_cache.get<byFullName>().end())
    return;

  freeEntry(it);
}

InMemoryStorage::const_iterator
InMemoryStorage::begin() const
{
  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().begin();

  return const_iterator(&((*it)->getData()), &m_cache, it);
}

InMemoryStorage::const_iterator
InMemoryStorage::end() const
{
  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().end();

  return const_iterator(nullptr, &m_cache, it);
}

void
InMemoryStorage::afterInsert(InMemoryStorageEntry* entry)
{
}

void
InMemoryStorage::beforeErase(InMemoryStorageEntry* entry)
{
}

void
InMemoryStorage::afterAccess(InMemoryStorageEntry* entry)
{
}

void
InMemoryStorage::printCache(std::ostream& os) const
{
  //start from the upper layer towards bottom
  const Cache::index<byFullName>::type& cacheIndex = m_cache.get<byFullName>();
  for (Cache::index<byFullName>::type::iterator it = cacheIndex.begin();
       it != cacheIndex.end(); it++)
    os << (*it)->getFullName() << std::endl;
}

} // namespace util
} // namespace ndn
