/* -*- 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 "rib-manager.hpp"
#include "core/global-io.hpp"
#include "core/logger.hpp"
#include "core/scheduler.hpp"
#include <ndn-cxx/management/nfd-face-status.hpp>
#include <ndn-cxx/management/nfd-rib-entry.hpp>

namespace nfd {
namespace rib {

NFD_LOG_INIT("RibManager");

const Name RibManager::LOCAL_HOST_TOP_PREFIX = "/localhost/nfd";
const Name RibManager::LOCAL_HOP_TOP_PREFIX = "/localhop/nfd";
const std::string RibManager::MGMT_MODULE_NAME = "rib";
const Name RibManager::FACES_LIST_DATASET_PREFIX = "/localhost/nfd/faces/list";
const time::seconds RibManager::ACTIVE_FACE_FETCH_INTERVAL = time::seconds(300);

RibManager::RibManager(Dispatcher& dispatcher,
                       ndn::Face& face,
                       ndn::KeyChain& keyChain)
  : ManagerBase(dispatcher, MGMT_MODULE_NAME)
  , m_face(face)
  , m_keyChain(keyChain)
  , m_nfdController(m_face, m_keyChain)
  , m_faceMonitor(m_face)
  , m_localhostValidator(m_face)
  , m_localhopValidator(m_face)
  , m_isLocalhopEnabled(false)
  , m_prefixPropagator(m_nfdController, m_keyChain, m_rib)
  , m_fibUpdater(m_rib, m_nfdController)
  , m_addTopPrefix([&dispatcher] (const Name& topPrefix) {
      dispatcher.addTopPrefix(topPrefix, false);
    })
{
  registerCommandHandler<ndn::nfd::RibRegisterCommand>("register",
    bind(&RibManager::registerEntry, this, _2, _3, _4, _5));
  registerCommandHandler<ndn::nfd::RibUnregisterCommand>("unregister",
    bind(&RibManager::unregisterEntry, this, _2, _3, _4, _5));

  registerStatusDatasetHandler("list", bind(&RibManager::listEntries, this, _1, _2, _3));
}

RibManager::~RibManager()
{
  scheduler::cancel(m_activeFaceFetchEvent);
}

void
RibManager::registerWithNfd()
{
  registerTopPrefix(LOCAL_HOST_TOP_PREFIX);

  if (m_isLocalhopEnabled) {
    registerTopPrefix(LOCAL_HOP_TOP_PREFIX);
  }

  NFD_LOG_INFO("Start monitoring face create/destroy events");
  m_faceMonitor.onNotification.connect(bind(&RibManager::onNotification, this, _1));
  m_faceMonitor.start();

  scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
}

void
RibManager::enableLocalControlHeader()
{
  m_nfdController.start<ndn::nfd::FaceEnableLocalControlCommand>(
    ControlParameters()
      .setLocalControlFeature(ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
    bind(&RibManager::onControlHeaderSuccess, this),
    bind(&RibManager::onControlHeaderError, this, _1, _2));
}

void
RibManager::setConfigFile(ConfigFile& configFile)
{
  configFile.addSectionHandler("rib",
                               bind(&RibManager::onConfig, this, _1, _2, _3));
}

void
RibManager::onRibUpdateSuccess(const RibUpdate& update)
{
  NFD_LOG_DEBUG("RIB update succeeded for " << update);
}

void
RibManager::onRibUpdateFailure(const RibUpdate& update, uint32_t code, const std::string& error)
{
  NFD_LOG_DEBUG("RIB update failed for " << update << " (code: " << code
                                                   << ", error: " << error << ")");

  // Since the FIB rejected the update, clean up invalid routes
  scheduleActiveFaceFetch(time::seconds(1));
}

void
RibManager::onConfig(const ConfigSection& configSection,
                     bool isDryRun,
                     const std::string& filename)
{
  bool isAutoPrefixPropagatorEnabled = false;

  for (const auto& item : configSection) {
    if (item.first == "localhost_security") {
      m_localhostValidator.load(item.second, filename);
    }
    else if (item.first == "localhop_security") {
      m_localhopValidator.load(item.second, filename);
      m_isLocalhopEnabled = true;
    }
    else if (item.first == "auto_prefix_propagate") {
      m_prefixPropagator.loadConfig(item.second);
      isAutoPrefixPropagatorEnabled = true;

      // Avoid other actions when isDryRun == true
      if (isDryRun) {
        continue;
      }

      m_prefixPropagator.enable();
    }
    else {
      BOOST_THROW_EXCEPTION(Error("Unrecognized rib property: " + item.first));
    }
  }

  if (!isAutoPrefixPropagatorEnabled) {
    m_prefixPropagator.disable();
  }
}

void
RibManager::registerTopPrefix(const Name& topPrefix)
{
  // register entry to the FIB
  m_nfdController.start<ndn::nfd::FibAddNextHopCommand>(
     ControlParameters()
       .setName(Name(topPrefix).append(MGMT_MODULE_NAME))
       .setFaceId(0),
     bind(&RibManager::onNrdCommandPrefixAddNextHopSuccess, this, cref(topPrefix), _1),
     bind(&RibManager::onNrdCommandPrefixAddNextHopError, this, cref(topPrefix), _2));

  // add top prefix to the dispatcher
  m_addTopPrefix(topPrefix);
}

void
RibManager::registerEntry(const Name& topPrefix, const Interest& interest,
                          ControlParameters parameters,
                          const ndn::mgmt::CommandContinuation& done)
{
  setFaceForSelfRegistration(interest, parameters);

  // Respond since command is valid and authorized
  done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));

  Route route;
  route.faceId = parameters.getFaceId();
  route.origin = parameters.getOrigin();
  route.cost = parameters.getCost();
  route.flags = parameters.getFlags();

  if (parameters.hasExpirationPeriod() &&
      parameters.getExpirationPeriod() != time::milliseconds::max())
  {
    route.expires = time::steady_clock::now() + parameters.getExpirationPeriod();

    // Schedule a new event, the old one will be cancelled during rib insertion.
    scheduler::EventId eventId = scheduler::schedule(parameters.getExpirationPeriod(),
      bind(&Rib::onRouteExpiration, &m_rib, parameters.getName(), route));

    NFD_LOG_TRACE("Scheduled unregistration at: " << route.expires <<
                  " with EventId: " << eventId);

    // Set the  NewEventId of this entry
    route.setExpirationEvent(eventId);
  }
  else {
    route.expires = time::steady_clock::TimePoint::max();
  }

  NFD_LOG_INFO("Adding route " << parameters.getName() << " nexthop=" << route.faceId
                                                       << " origin=" << route.origin
                                                       << " cost=" << route.cost);

  RibUpdate update;
  update.setAction(RibUpdate::REGISTER)
        .setName(parameters.getName())
        .setRoute(route);

  m_rib.beginApplyUpdate(update,
                                bind(&RibManager::onRibUpdateSuccess, this, update),
                                bind(&RibManager::onRibUpdateFailure, this, update, _1, _2));

  m_registeredFaces.insert(route.faceId);
}

void
RibManager::unregisterEntry(const Name& topPrefix, const Interest& interest,
                            ControlParameters parameters,
                            const ndn::mgmt::CommandContinuation& done)
{
  setFaceForSelfRegistration(interest, parameters);

  // Respond since command is valid and authorized
  done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));

  Route route;
  route.faceId = parameters.getFaceId();
  route.origin = parameters.getOrigin();

  NFD_LOG_INFO("Removing route " << parameters.getName() << " nexthop=" << route.faceId
                                                         << " origin=" << route.origin);

  RibUpdate update;
  update.setAction(RibUpdate::UNREGISTER)
        .setName(parameters.getName())
        .setRoute(route);

  m_rib.beginApplyUpdate(update,
                                bind(&RibManager::onRibUpdateSuccess, this, update),
                                bind(&RibManager::onRibUpdateFailure, this, update, _1, _2));
}

void
RibManager::listEntries(const Name& topPrefix, const Interest& interest,
                        ndn::mgmt::StatusDatasetContext& context)
{
  for (auto&& ribTableEntry : m_rib) {
    const auto& ribEntry = *ribTableEntry.second;
    ndn::nfd::RibEntry record;

    for (auto&& route : ribEntry) {
      ndn::nfd::Route routeElement;
      routeElement.setFaceId(route.faceId)
              .setOrigin(route.origin)
              .setCost(route.cost)
              .setFlags(route.flags);

      if (route.expires < time::steady_clock::TimePoint::max()) {
        routeElement.setExpirationPeriod(time::duration_cast<time::milliseconds>(
          route.expires - time::steady_clock::now()));
      }

      record.addRoute(routeElement);
    }

    record.setName(ribEntry.getName());
    context.append(record.wireEncode());
  }

  context.end();
}

void
RibManager::setFaceForSelfRegistration(const Interest& request, ControlParameters& parameters)
{
  bool isSelfRegistration = (parameters.getFaceId() == 0);
  if (isSelfRegistration) {
    shared_ptr<lp::IncomingFaceIdTag> incomingFaceIdTag = request.getTag<lp::IncomingFaceIdTag>();
    // NDNLPv2 says "application MUST be prepared to receive a packet without IncomingFaceId field",
    // but it's fine to assert IncomingFaceId is available, because InternalFace lives inside NFD
    // and is initialized synchronously with IncomingFaceId field enabled.
    BOOST_ASSERT(incomingFaceIdTag != nullptr);
    parameters.setFaceId(*incomingFaceIdTag);
  }
}

void
RibManager::authorize(const Name& prefix, const Interest& interest,
                      const ndn::mgmt::ControlParameters* params,
                      ndn::mgmt::AcceptContinuation accept,
                      ndn::mgmt::RejectContinuation reject)
{
  BOOST_ASSERT(params != nullptr);
  BOOST_ASSERT(typeid(*params) == typeid(ndn::nfd::ControlParameters));
  BOOST_ASSERT(prefix == LOCAL_HOST_TOP_PREFIX || prefix == LOCAL_HOP_TOP_PREFIX);

  auto& validator = [this, &prefix] () -> ndn::ValidatorConfig & {
    return prefix == LOCAL_HOST_TOP_PREFIX ? m_localhostValidator : m_localhopValidator;
  }();

  validator.validate(interest,
                     bind([&interest, this, accept] { extractRequester(interest, accept); }),
                     bind([reject] { reject(ndn::mgmt::RejectReply::STATUS403); }));
}

void
RibManager::fetchActiveFaces()
{
  NFD_LOG_DEBUG("Fetching active faces");

  Interest interest(FACES_LIST_DATASET_PREFIX);
  interest.setChildSelector(1);
  interest.setMustBeFresh(true);

  shared_ptr<ndn::OBufferStream> buffer = make_shared<ndn::OBufferStream>();

  m_face.expressInterest(interest,
                         bind(&RibManager::fetchSegments, this, _2, buffer),
                         bind(&RibManager::onFetchFaceStatusTimeout, this));
}

void
RibManager::fetchSegments(const Data& data, shared_ptr<ndn::OBufferStream> buffer)
{
  buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
                data.getContent().value_size());

  uint64_t currentSegment = data.getName().get(-1).toSegment();

  const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();

  if (finalBlockId.empty() || finalBlockId.toSegment() > currentSegment) {
    m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
                           bind(&RibManager::fetchSegments, this, _2, buffer),
                           bind(&RibManager::onFetchFaceStatusTimeout, this));
  }
  else {
    removeInvalidFaces(buffer);
  }
}

void
RibManager::onFetchFaceStatusTimeout()
{
  std::cerr << "Face Status Dataset request timed out" << std::endl;
  scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
}

void
RibManager::onFaceDestroyedEvent(uint64_t faceId)
{
  m_rib.beginRemoveFace(faceId);
  m_registeredFaces.erase(faceId);
}

void
RibManager::scheduleActiveFaceFetch(const time::seconds& timeToWait)
{
  scheduler::cancel(m_activeFaceFetchEvent);

  m_activeFaceFetchEvent = scheduler::schedule(timeToWait,
                                               bind(&RibManager::fetchActiveFaces, this));
}

void
RibManager::removeInvalidFaces(shared_ptr<ndn::OBufferStream> buffer)
{
  NFD_LOG_DEBUG("Checking for invalid face registrations");

  ndn::ConstBufferPtr buf = buffer->buf();

  Block block;
  size_t offset = 0;
  FaceIdSet activeFaces;

  while (offset < buf->size()) {
    bool isOk = false;
    std::tie(isOk, block) = Block::fromBuffer(buf, offset);
    if (!isOk) {
      std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
      break;
    }

    offset += block.size();

    ndn::nfd::FaceStatus status(block);
    activeFaces.insert(status.getFaceId());
  }

  // Look for face IDs that were registered but not active to find missed
  // face destroyed events
  for (auto&& faceId : m_registeredFaces) {
    if (activeFaces.find(faceId) == activeFaces.end()) {
      NFD_LOG_DEBUG("Removing invalid face ID: " << faceId);

      scheduler::schedule(time::seconds(0),
                          bind(&RibManager::onFaceDestroyedEvent, this, faceId));
    }
  }

  // Reschedule the check for future clean up
  scheduleActiveFaceFetch(ACTIVE_FACE_FETCH_INTERVAL);
}

void
RibManager::onNotification(const FaceEventNotification& notification)
{
  NFD_LOG_TRACE("onNotification: " << notification);

  if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) {
    NFD_LOG_DEBUG("Received notification for destroyed faceId: " << notification.getFaceId());

    scheduler::schedule(time::seconds(0),
                        bind(&RibManager::onFaceDestroyedEvent, this, notification.getFaceId()));
  }
}

void
RibManager::onNrdCommandPrefixAddNextHopSuccess(const Name& prefix,
                                                const ndn::nfd::ControlParameters& result)
{
  NFD_LOG_DEBUG("Successfully registered " + prefix.toUri() + " with NFD");

  // Routes must be inserted into the RIB so route flags can be applied
  Route route;
  route.faceId = result.getFaceId();
  route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
  route.expires = time::steady_clock::TimePoint::max();
  route.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;

  m_rib.insert(prefix, route);

  m_registeredFaces.insert(route.faceId);
}

void
RibManager::onNrdCommandPrefixAddNextHopError(const Name& name, const std::string& msg)
{
  BOOST_THROW_EXCEPTION(Error("Error in setting interest filter (" + name.toUri() + "): " + msg));
}

void
RibManager::onControlHeaderSuccess()
{
  NFD_LOG_DEBUG("Local control header enabled");
}

void
RibManager::onControlHeaderError(uint32_t code, const std::string& reason)
{
  std::ostringstream os;
  os << "Couldn't enable local control header "
     << "(code: " << code << ", info: " << reason << ")";
  BOOST_THROW_EXCEPTION(Error(os.str()));
}

} // namespace rib
} // namespace nfd
