/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022,  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 "measurements.hpp"
#include "name-tree.hpp"
#include "pit-entry.hpp"
#include "fib-entry.hpp"
#include "common/global.hpp"

namespace nfd::measurements {

Measurements::Measurements(NameTree& nameTree)
  : m_nameTree(nameTree)
{
}

Entry&
Measurements::get(name_tree::Entry& nte)
{
  Entry* entry = nte.getMeasurementsEntry();
  if (entry != nullptr) {
    return *entry;
  }

  nte.setMeasurementsEntry(make_unique<Entry>(nte.getName()));
  ++m_nItems;
  entry = nte.getMeasurementsEntry();

  entry->m_expiry = time::steady_clock::now() + getInitialLifetime();
  entry->m_cleanup = getScheduler().schedule(getInitialLifetime(), [=] { cleanup(*entry); });

  return *entry;
}

Entry&
Measurements::get(const Name& name)
{
  name_tree::Entry& nte = m_nameTree.lookup(name, std::min(name.size(), getMaxDepth()));
  return this->get(nte);
}

Entry&
Measurements::get(const fib::Entry& fibEntry)
{
  name_tree::Entry& nte = m_nameTree.lookup(fibEntry);
  return this->get(nte);
}

Entry&
Measurements::get(const pit::Entry& pitEntry)
{
  name_tree::Entry& nte = m_nameTree.lookup(pitEntry);
  return this->get(nte);
}

Entry*
Measurements::getParent(const Entry& child)
{
  if (child.getName().empty()) { // the root entry
    return nullptr;
  }

  name_tree::Entry* nteChild = m_nameTree.getEntry(child);
  name_tree::Entry* nte = nteChild->getParent();
  BOOST_ASSERT(nte != nullptr);
  return &this->get(*nte);
}

template<typename K>
Entry*
Measurements::findLongestPrefixMatchImpl(const K& key, const EntryPredicate& pred) const
{
  name_tree::Entry* match = m_nameTree.findLongestPrefixMatch(key,
    [&pred] (const name_tree::Entry& nte) {
      const Entry* entry = nte.getMeasurementsEntry();
      return entry != nullptr && pred(*entry);
    });
  if (match != nullptr) {
    return match->getMeasurementsEntry();
  }
  return nullptr;
}

Entry*
Measurements::findLongestPrefixMatch(const Name& name, const EntryPredicate& pred) const
{
  return this->findLongestPrefixMatchImpl(name.getPrefix(NameTree::getMaxDepth()), pred);
}

Entry*
Measurements::findLongestPrefixMatch(const pit::Entry& pitEntry, const EntryPredicate& pred) const
{
  return this->findLongestPrefixMatch(pitEntry.getName(), pred);
}

Entry*
Measurements::findExactMatch(const Name& name) const
{
  const name_tree::Entry* nte = m_nameTree.findExactMatch(name);
  return nte == nullptr ? nullptr : nte->getMeasurementsEntry();
}

void
Measurements::extendLifetime(Entry& entry, const time::nanoseconds& lifetime)
{
  BOOST_ASSERT(m_nameTree.getEntry(entry) != nullptr);

  auto expiry = time::steady_clock::now() + lifetime;
  if (entry.m_expiry >= expiry) {
    // has longer lifetime, not extending
    return;
  }

  entry.m_cleanup.cancel();
  entry.m_expiry = expiry;
  entry.m_cleanup = getScheduler().schedule(lifetime, [&] { cleanup(entry); });
}

void
Measurements::cleanup(Entry& entry)
{
  name_tree::Entry* nte = m_nameTree.getEntry(entry);
  BOOST_ASSERT(nte != nullptr);

  nte->setMeasurementsEntry(nullptr);
  m_nameTree.eraseIfEmpty(nte);
  --m_nItems;
}

} // namespace nfd::measurements
