/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2018,  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 "core/logger.hpp"
#include "core/random.hpp"

namespace nfd {
namespace rib {

NFD_LOG_INIT(Readvertise);

const time::milliseconds Readvertise::RETRY_DELAY_MIN = 50_s;
const time::milliseconds Readvertise::RETRY_DELAY_MAX = 3600_s;

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

Readvertise::Readvertise(Rib& rib, ndn::util::Scheduler& scheduler,
                         unique_ptr<ReadvertisePolicy> policy,
                         unique_ptr<ReadvertiseDestination> destination)
  : m_scheduler(scheduler)
  , 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)
{
  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;
  }

  ReadvertisedRouteContainer::iterator rrIt;
  bool isNew = false;
  std::tie(rrIt, isNew) = m_rrs.emplace(action->prefix, m_scheduler);

  if (!isNew && 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;

  RouteRrIndex::iterator indexIt;
  std::tie(indexIt, isNew) = m_routeToRr.emplace(ribRoute, rrIt);
  BOOST_ASSERT(isNew);

  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 = m_scheduler.scheduleEvent(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 = m_scheduler.scheduleEvent(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 = m_scheduler.scheduleEvent(randomizeTimer(rrIt->retryDelay),
                                                 [=] { withdraw(rrIt); });
    });
}

} // namespace rib
} // namespace nfd
