/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2016,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "name-tree.hpp"
#include "core/logger.hpp"

#include <boost/concept/assert.hpp>
#include <boost/concept_check.hpp>
#include <type_traits>

namespace nfd {
namespace name_tree {

NFD_LOG_INIT("NameTree");

NameTree::NameTree(size_t nBuckets)
  : m_ht(HashtableOptions(nBuckets))
{
}

Entry&
NameTree::lookup(const Name& name)
{
  NFD_LOG_TRACE("lookup " << name);

  HashSequence hashes = computeHashes(name);
  const Node* node = nullptr;
  Entry* parent = nullptr;

  for (size_t prefixLen = 0; prefixLen <= name.size(); ++prefixLen) {
    bool isNew = false;
    std::tie(node, isNew) = m_ht.insert(name, prefixLen, hashes);

    if (isNew && parent != nullptr) {
      node->entry->setParent(*parent);
    }
    parent = node->entry.get();
  }
  return *node->entry;
}

Entry&
NameTree::lookup(const fib::Entry& fibEntry)
{
  Entry* nte = this->getEntry(fibEntry);
  if (nte == nullptr) {
    // special case: Fib::s_emptyEntry is unattached
    BOOST_ASSERT(fibEntry.getPrefix().empty());
    return this->lookup(fibEntry.getPrefix());
  }

  BOOST_ASSERT(nte->getFibEntry() == &fibEntry);
  return *nte;
}

Entry&
NameTree::lookup(const pit::Entry& pitEntry)
{
  Entry* nte = this->getEntry(pitEntry);
  BOOST_ASSERT(nte != nullptr);

  BOOST_ASSERT(std::count_if(nte->getPitEntries().begin(), nte->getPitEntries().end(),
    [&pitEntry] (const shared_ptr<pit::Entry>& pitEntry1) {
      return pitEntry1.get() == &pitEntry;
    }) == 1);

  if (nte->getName().size() == pitEntry.getName().size()) {
    return *nte;
  }

  // special case: PIT entry whose Interest name ends with an implicit digest
  // are attached to the name tree entry with one-shorter-prefix.
  BOOST_ASSERT(pitEntry.getName().at(-1).isImplicitSha256Digest());
  BOOST_ASSERT(nte->getName() == pitEntry.getName().getPrefix(-1));
  return this->lookup(pitEntry.getName());
}

Entry&
NameTree::lookup(const measurements::Entry& measurementsEntry)
{
  Entry* nte = this->getEntry(measurementsEntry);
  BOOST_ASSERT(nte != nullptr);

  BOOST_ASSERT(nte->getMeasurementsEntry() == &measurementsEntry);
  return *nte;
}

Entry&
NameTree::lookup(const strategy_choice::Entry& strategyChoiceEntry)
{
  Entry* nte = this->getEntry(strategyChoiceEntry);
  BOOST_ASSERT(nte != nullptr);

  BOOST_ASSERT(nte->getStrategyChoiceEntry() == &strategyChoiceEntry);
  return *nte;
}

size_t
NameTree::eraseIfEmpty(Entry* entry)
{
  BOOST_ASSERT(entry != nullptr);

  size_t nErased = 0;
  for (Entry* parent = nullptr; entry != nullptr && entry->isEmpty(); entry = parent) {
    parent = entry->getParent();

    if (parent != nullptr) {
      entry->unsetParent();
    }

    m_ht.erase(getNode(*entry));
    ++nErased;
  }

  if (nErased == 0) {
    NFD_LOG_TRACE("not-erase " << entry->getName());
  }
  return nErased;
}

Entry*
NameTree::findExactMatch(const Name& name) const
{
  const Node* node = m_ht.find(name, name.size());
  return node == nullptr ? nullptr : node->entry.get();
}

Entry*
NameTree::findLongestPrefixMatch(const Name& name, const EntrySelector& entrySelector) const
{
  HashSequence hashes = computeHashes(name);

  for (ssize_t prefixLen = name.size(); prefixLen >= 0; --prefixLen) {
    const Node* node = m_ht.find(name, prefixLen, hashes);
    if (node != nullptr && entrySelector(*node->entry)) {
      return node->entry.get();
    }
  }

  return nullptr;
}

Entry*
NameTree::findLongestPrefixMatch(const Entry& entry1, const EntrySelector& entrySelector) const
{
  Entry* entry = const_cast<Entry*>(&entry1);
  while (entry != nullptr) {
    if (entrySelector(*entry)) {
      return entry;
    }
    entry = entry->getParent();
  }
  return nullptr;
}

template<typename ENTRY>
Entry*
NameTree::findLongestPrefixMatch(const ENTRY& tableEntry, const EntrySelector& entrySelector) const
{
  const Entry* nte = this->getEntry(tableEntry);
  BOOST_ASSERT(nte != nullptr);
  return this->findLongestPrefixMatch(*nte, entrySelector);
}

template Entry*
NameTree::findLongestPrefixMatch<fib::Entry>(const fib::Entry&, const EntrySelector&) const;

template Entry*
NameTree::findLongestPrefixMatch<measurements::Entry>(const measurements::Entry&,
                                                      const EntrySelector&) const;

template Entry*
NameTree::findLongestPrefixMatch<strategy_choice::Entry>(const strategy_choice::Entry&,
                                                         const EntrySelector&) const;

Entry*
NameTree::findLongestPrefixMatch(const pit::Entry& pitEntry, const EntrySelector& entrySelector) const
{
  const Entry* nte = this->getEntry(pitEntry);
  BOOST_ASSERT(nte != nullptr);

  if (nte->getName().size() < pitEntry.getName().size()) {
    // special case: PIT entry whose Interest name ends with an implicit digest
    // are attached to the name tree entry with one-shorter-prefix.
    BOOST_ASSERT(pitEntry.getName().at(-1).isImplicitSha256Digest());
    BOOST_ASSERT(nte->getName() == pitEntry.getName().getPrefix(-1));
    const Entry* exact = this->findExactMatch(pitEntry.getName());
    if (exact != nullptr) {
      nte = exact;
    }
  }

  return this->findLongestPrefixMatch(*nte, entrySelector);
}

boost::iterator_range<NameTree::const_iterator>
NameTree::findAllMatches(const Name& name, const EntrySelector& entrySelector) const
{
  // As we are using Name Prefix Hash Table, and the current LPM() is
  // implemented as starting from full name, and reduce the number of
  // components by 1 each time, we could use it here.
  // For trie-like design, it could be more efficient by walking down the
  // trie from the root node.

  Entry* entry = this->findLongestPrefixMatch(name, entrySelector);
  return {Iterator(make_shared<PrefixMatchImpl>(*this, entrySelector), entry), end()};
}

boost::iterator_range<NameTree::const_iterator>
NameTree::fullEnumerate(const EntrySelector& entrySelector) const
{
  return {Iterator(make_shared<FullEnumerationImpl>(*this, entrySelector), nullptr), end()};
}

boost::iterator_range<NameTree::const_iterator>
NameTree::partialEnumerate(const Name& prefix,
                           const EntrySubTreeSelector& entrySubTreeSelector) const
{
  Entry* entry = this->findExactMatch(prefix);
  return {Iterator(make_shared<PartialEnumerationImpl>(*this, entrySubTreeSelector), entry), end()};
}

} // namespace name_tree
} // namespace nfd
