/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2019,  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 "asf-measurements.hpp"
#include "daemon/global.hpp"

namespace nfd {
namespace fw {
namespace asf {

NFD_LOG_INIT(AsfMeasurements);

const RttStats::Rtt RttStats::RTT_TIMEOUT(-1.0);
const RttStats::Rtt RttStats::RTT_NO_MEASUREMENT(0.0);
const double RttStats::ALPHA = 0.125;

RttStats::RttStats()
  : m_srtt(RTT_NO_MEASUREMENT)
  , m_rtt(RTT_NO_MEASUREMENT)
{
}

void
RttStats::addRttMeasurement(RttEstimator::Duration& durationRtt)
{
  m_rtt = static_cast<RttStats::Rtt>(durationRtt.count());

  m_rttEstimator.addMeasurement(durationRtt);

  m_srtt = computeSrtt(m_srtt, m_rtt);
}

RttStats::Rtt
RttStats::computeSrtt(Rtt previousSrtt, Rtt currentRtt)
{
  if (previousSrtt == RTT_NO_MEASUREMENT) {
    return currentRtt;
  }

  return Rtt(ALPHA * currentRtt + (1 - ALPHA) * previousSrtt);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

FaceInfo::FaceInfo()
  : m_isTimeoutScheduled(false)
  , m_nSilentTimeouts(0)
{
}

FaceInfo::~FaceInfo()
{
  cancelTimeoutEvent();
  m_measurementExpirationId.cancel();
}

void
FaceInfo::setTimeoutEvent(const scheduler::EventId& id, const Name& interestName)
{
  if (!m_isTimeoutScheduled) {
    m_timeoutEventId = id;
    m_isTimeoutScheduled = true;
    m_lastInterestName = interestName;
  }
  else {
    NDN_THROW(FaceInfo::Error("Tried to schedule a timeout for a face that already has a timeout scheduled"));
  }
}

void
FaceInfo::cancelTimeoutEvent()
{
  m_timeoutEventId.cancel();
  m_isTimeoutScheduled = false;
}

void
FaceInfo::cancelTimeoutEvent(const Name& prefix)
{
  if (isTimeoutScheduled() && doesNameMatchLastInterest(prefix)) {
    cancelTimeoutEvent();
  }
}

bool
FaceInfo::doesNameMatchLastInterest(const Name& name)
{
  return m_lastInterestName.isPrefixOf(name);
}

void
FaceInfo::recordRtt(const shared_ptr<pit::Entry>& pitEntry, const Face& inFace)
{
  // Calculate RTT
  auto outRecord = pitEntry->getOutRecord(inFace, 0);

  if (outRecord == pitEntry->out_end()) { // no out-record
    NFD_LOG_TRACE(pitEntry->getInterest() << " dataFrom inFace=" << inFace.getId() << " no-out-record");
    return;
  }

  time::steady_clock::Duration steadyRtt = time::steady_clock::now() - outRecord->getLastRenewed();
  auto durationRtt = time::duration_cast<RttEstimator::Duration>(steadyRtt);

  m_rttStats.addRttMeasurement(durationRtt);

  NFD_LOG_TRACE("Recording RTT for FaceId: " << inFace.getId()
                                             << " RTT: "    << m_rttStats.getRtt()
                                             << " SRTT: "   << m_rttStats.getSrtt());
}

void
FaceInfo::recordTimeout(const Name& interestName)
{
  m_rttStats.recordTimeout();
  cancelTimeoutEvent(interestName);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

NamespaceInfo::NamespaceInfo()
  : m_isProbingDue(false)
  , m_hasFirstProbeBeenScheduled(false)
{
}

FaceInfo*
NamespaceInfo::getFaceInfo(const fib::Entry&, FaceId faceId)
{
  auto it = m_fit.find(faceId);
  if (it != m_fit.end()) {
    return &it->second;
  }
  else {
    return nullptr;
  }
}

FaceInfo&
NamespaceInfo::getOrCreateFaceInfo(const fib::Entry&, FaceId faceId)
{
  auto it = m_fit.find(faceId);
  FaceInfo* info = nullptr;

  if (it == m_fit.end()) {
    const auto& pair = m_fit.emplace(faceId, FaceInfo());
    info = &pair.first->second;

    extendFaceInfoLifetime(*info, faceId);
  }
  else {
    info = &it->second;
  }

  return *info;
}

void
NamespaceInfo::expireFaceInfo(FaceId faceId)
{
  m_fit.erase(faceId);
}

void
NamespaceInfo::extendFaceInfoLifetime(FaceInfo& info, FaceId faceId)
{
  // Cancel previous expiration
  info.getMeasurementExpirationEventId().cancel();

  // Refresh measurement
  auto id = getScheduler().schedule(AsfMeasurements::MEASUREMENTS_LIFETIME,
                                    [=] { expireFaceInfo(faceId); });
  info.setMeasurementExpirationEventId(id);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

constexpr time::microseconds AsfMeasurements::MEASUREMENTS_LIFETIME;

AsfMeasurements::AsfMeasurements(MeasurementsAccessor& measurements)
  : m_measurements(measurements)
{
}

FaceInfo*
AsfMeasurements::getFaceInfo(const fib::Entry& fibEntry, const Interest& interest, FaceId faceId)
{
  NamespaceInfo& info = getOrCreateNamespaceInfo(fibEntry, interest);
  return info.getFaceInfo(fibEntry, faceId);
}

FaceInfo&
AsfMeasurements::getOrCreateFaceInfo(const fib::Entry& fibEntry, const Interest& interest,
                                     FaceId faceId)
{
  NamespaceInfo& info = getOrCreateNamespaceInfo(fibEntry, interest);
  return info.getOrCreateFaceInfo(fibEntry, faceId);
}

NamespaceInfo*
AsfMeasurements::getNamespaceInfo(const Name& prefix)
{
  measurements::Entry* me = m_measurements.findLongestPrefixMatch(prefix);
  if (me == nullptr) {
    return nullptr;
  }

  // Set or update entry lifetime
  extendLifetime(*me);

  NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>().first;
  BOOST_ASSERT(info != nullptr);
  return info;
}

NamespaceInfo&
AsfMeasurements::getOrCreateNamespaceInfo(const fib::Entry& fibEntry, const Interest& interest)
{
  measurements::Entry* me = m_measurements.get(fibEntry);

  // If the FIB entry is not under the strategy's namespace, find a part of the prefix
  // that falls under the strategy's namespace
  for (size_t prefixLen = fibEntry.getPrefix().size() + 1;
       me == nullptr && prefixLen <= interest.getName().size(); ++prefixLen) {
    me = m_measurements.get(interest.getName().getPrefix(prefixLen));
  }

  // Either the FIB entry or the Interest's name must be under this strategy's namespace
  BOOST_ASSERT(me != nullptr);

  // Set or update entry lifetime
  extendLifetime(*me);

  NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>().first;
  BOOST_ASSERT(info != nullptr);
  return *info;
}

void
AsfMeasurements::extendLifetime(measurements::Entry& me)
{
  m_measurements.extendLifetime(me, MEASUREMENTS_LIFETIME);
}

} // namespace asf
} // namespace fw
} // namespace nfd
