/* -*- 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 "readvertise.hpp"
#include "common/global.hpp"
#include "common/logger.hpp"

#include <ndn-cxx/util/random.hpp>

namespace nfd::rib {

NFD_LOG_INIT(Readvertise);

constexpr time::milliseconds RETRY_DELAY_MIN = 50_s;
constexpr time::milliseconds RETRY_DELAY_MAX = 1_h;

static time::milliseconds
randomizeTimer(time::milliseconds baseTimer)
{
  std::uniform_int_distribution<> dist(-5, 5);
  auto newTime = baseTimer + time::milliseconds(dist(ndn::random::getRandomNumberEngine()));
  return std::max(newTime, 0_ms);
}

Readvertise::Readvertise(Rib& rib,
                         unique_ptr<ReadvertisePolicy> policy,
                         unique_ptr<ReadvertiseDestination> destination)
  : m_policy(std::move(policy))
  , m_destination(std::move(destination))
{
  m_addRouteConn = rib.afterAddRoute.connect([this] (const auto& r) { this->afterAddRoute(r); });
  m_removeRouteConn = rib.beforeRemoveRoute.connect([this] (const auto& r) { this->beforeRemoveRoute(r); });

  m_destination->afterAvailabilityChange.connect([this] (bool isAvailable) {
    if (isAvailable) {
      this->afterDestinationAvailable();
    }
    else {
      this->afterDestinationUnavailable();
    }
  });
}

void
Readvertise::afterAddRoute(const RibRouteRef& ribRoute)
{
  std::optional<ReadvertiseAction> action = m_policy->handleNewRoute(ribRoute);
  if (!action) {
    NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
                  ',' << ribRoute.route->origin << ") not-readvertising");
    return;
  }

  auto [rrIt, isNewRr] = m_rrs.emplace(action->prefix);
  if (!isNewRr && rrIt->signer != action->signer) {
    NFD_LOG_WARN("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
                 ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
                 " old-signer " << rrIt->signer << " new-signer " << action->signer);
  }
  rrIt->signer = action->signer;

  bool isNewInMap = m_routeToRr.try_emplace(ribRoute, rrIt).second;
  BOOST_VERIFY(isNewInMap);

  if (rrIt->nRibRoutes++ > 0) {
    NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
                  ',' << ribRoute.route->origin << ") already-readvertised-as " << action->prefix);
    return;
  }

  NFD_LOG_DEBUG("add-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
                ',' << ribRoute.route->origin << ") readvertising-as " << action->prefix <<
                " signer " << action->signer);
  rrIt->retryDelay = RETRY_DELAY_MIN;
  this->advertise(rrIt);
}

void
Readvertise::beforeRemoveRoute(const RibRouteRef& ribRoute)
{
  auto indexIt = m_routeToRr.find(ribRoute);
  if (indexIt == m_routeToRr.end()) {
    NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
                  ',' << ribRoute.route->origin << ") not-readvertised");
    return;
  }

  auto rrIt = indexIt->second;
  m_routeToRr.erase(indexIt);

  if (--rrIt->nRibRoutes > 0) {
    NFD_LOG_DEBUG("remove-route " << ribRoute.entry->getName() << '(' << ribRoute.route->faceId <<
                  ',' << ribRoute.route->origin << ") needed-by " << rrIt->nRibRoutes);
    return;
  }

  rrIt->retryDelay = RETRY_DELAY_MIN;
  this->withdraw(rrIt);
}

void
Readvertise::afterDestinationAvailable()
{
  for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end(); ++rrIt) {
    rrIt->retryDelay = RETRY_DELAY_MIN;
    this->advertise(rrIt);
  }
}

void
Readvertise::afterDestinationUnavailable()
{
  for (auto rrIt = m_rrs.begin(); rrIt != m_rrs.end();) {
    if (rrIt->nRibRoutes > 0) {
      rrIt->retryEvt.cancel(); // stop retrying or refreshing
      ++rrIt;
    }
    else {
      rrIt = m_rrs.erase(rrIt); // assume withdraw has completed
    }
  }
}

void
Readvertise::advertise(ReadvertisedRouteContainer::iterator rrIt)
{
  BOOST_ASSERT(rrIt->nRibRoutes > 0);

  if (!m_destination->isAvailable()) {
    NFD_LOG_DEBUG("advertise " << rrIt->prefix << " destination-unavailable");
    return;
  }

  m_destination->advertise(*rrIt,
    [=] {
      NFD_LOG_DEBUG("advertise " << rrIt->prefix << " success");
      rrIt->retryDelay = RETRY_DELAY_MIN;
      rrIt->retryEvt = getScheduler().schedule(randomizeTimer(m_policy->getRefreshInterval()),
                                               [=] { advertise(rrIt); });
    },
    [=] (const std::string& msg) {
      NFD_LOG_DEBUG("advertise " << rrIt->prefix << " failure " << msg);
      rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
      rrIt->retryEvt = getScheduler().schedule(randomizeTimer(rrIt->retryDelay),
                                               [=] { advertise(rrIt); });
    });
}

void
Readvertise::withdraw(ReadvertisedRouteContainer::iterator rrIt)
{
  BOOST_ASSERT(rrIt->nRibRoutes == 0);

  if (!m_destination->isAvailable()) {
    NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " destination-unavailable");
    m_rrs.erase(rrIt);
    return;
  }

  m_destination->withdraw(*rrIt,
    [=] {
      NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " success");
      m_rrs.erase(rrIt);
    },
    [=] (const std::string& msg) {
      NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " failure " << msg);
      rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
      rrIt->retryEvt = getScheduler().schedule(randomizeTimer(rrIt->retryDelay),
                                               [=] { withdraw(rrIt); });
    });
}

} // namespace nfd::rib
