/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2017,  The University of Memphis,
 *                           Regents of the University of California,
 *                           Arizona Board of Regents.
 *
 * This file is part of NLSR (Named-data Link State Routing).
 * See AUTHORS.md for complete list of NLSR authors and contributors.
 *
 * NLSR 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.
 *
 * NLSR 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
 * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "prefix-update-processor.hpp"

#include "lsdb.hpp"
#include "nlsr.hpp"
#include "prefix-update-commands.hpp"

#include <ndn-cxx/mgmt/nfd/control-response.hpp>

namespace nlsr {
namespace update {

INIT_LOGGER("PrefixUpdateProcessor");

const ndn::Name::Component PrefixUpdateProcessor::MODULE_COMPONENT = ndn::Name::Component("prefix-update");
const ndn::Name::Component PrefixUpdateProcessor::ADVERTISE_VERB = ndn::Name::Component("advertise");
const ndn::Name::Component PrefixUpdateProcessor::WITHDRAW_VERB  = ndn::Name::Component("withdraw");

PrefixUpdateProcessor::PrefixUpdateProcessor(ndn::Face& face,
                                             NamePrefixList& namePrefixList,
                                             Lsdb& lsdb,
                                             const ndn::Name broadcastPrefix,
                                             ndn::KeyChain& keyChain,
                                             std::shared_ptr<ndn::CertificateCacheTtl> certificateCache,
                                             security::CertificateStore& certStore)
  : m_face(face)
  , m_namePrefixList(namePrefixList)
  , m_lsdb(lsdb)
  , m_keyChain(keyChain)
  , m_validator(m_face, broadcastPrefix, certificateCache, certStore)
  , m_isEnabled(false)
  , COMMAND_PREFIX(ndn::Name(Nlsr::LOCALHOST_PREFIX).append(MODULE_COMPONENT))
{
}

void
PrefixUpdateProcessor::startListening()
{
  _LOG_DEBUG("Setting Interest filter for: " << COMMAND_PREFIX);

  m_face.setInterestFilter(COMMAND_PREFIX, std::bind(&PrefixUpdateProcessor::onInterest, this, _2));
}

void
PrefixUpdateProcessor::onInterest(const ndn::Interest& request)
{
  _LOG_TRACE("Received Interest: " << request);

  if (!m_isEnabled) {
    sendNack(request);
    return;
  }

  m_validator.validate(request,
                       std::bind(&PrefixUpdateProcessor::onCommandValidated, this, _1),
                       std::bind(&PrefixUpdateProcessor::onCommandValidationFailed, this, _1, _2));
}

void
PrefixUpdateProcessor::loadValidator(boost::property_tree::ptree section,
                                     const std::string& filename)
{
  m_validator.load(section, filename);
}

void
PrefixUpdateProcessor::onCommandValidated(const std::shared_ptr<const ndn::Interest>& request)
{
  const ndn::Name& command = request->getName();
  const ndn::Name::Component& verb = command[COMMAND_PREFIX.size()];
  const ndn::Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];

  if (verb == ADVERTISE_VERB || verb == WITHDRAW_VERB) {
    ndn::nfd::ControlParameters parameters;

    if (!extractParameters(parameterComponent, parameters)) {
      sendResponse(request, 400, "Malformed command");
      return;
    }

    if (verb == ADVERTISE_VERB) {
      advertise(request, parameters);
    }
    else if (verb == WITHDRAW_VERB) {
      withdraw(request, parameters);
    }

    sendResponse(request, 200, "Success");
  }
  else {
    sendResponse(request, 501, "Unsupported command");
  }
}

void
PrefixUpdateProcessor::onCommandValidationFailed(const std::shared_ptr<const ndn::Interest>& request,
                                                 const std::string& failureInfo)
{
  sendResponse(request, 403, failureInfo);
}

bool
PrefixUpdateProcessor::extractParameters(const ndn::Name::Component& parameterComponent,
                                         ndn::nfd::ControlParameters& extractedParameters)
{
  try {
    ndn::Block rawParameters = parameterComponent.blockFromValue();
    extractedParameters.wireDecode(rawParameters);
  }
  catch (const ndn::tlv::Error&) {
    return false;
  }

  return true;
}

void
PrefixUpdateProcessor::advertise(const std::shared_ptr<const ndn::Interest>& request,
                                 const ndn::nfd::ControlParameters& parameters)
{
  AdvertisePrefixCommand command;

  if (!validateParameters(command, parameters)) {
    sendResponse(request, 400, "Malformed command");
    return;
  }

  _LOG_INFO("Advertising name: " << parameters.getName());

  if (m_namePrefixList.insert(parameters.getName())) {
    // Only build a Name LSA if the added name is new
    m_lsdb.buildAndInstallOwnNameLsa();
  }
}

void
PrefixUpdateProcessor::withdraw(const std::shared_ptr<const ndn::Interest>& request,
                                const ndn::nfd::ControlParameters& parameters)
{
  WithdrawPrefixCommand command;

  if (!validateParameters(command, parameters)) {
    sendResponse(request, 400, "Malformed command");
    return;
  }

  _LOG_INFO("Withdrawing name: " << parameters.getName());

  if (m_namePrefixList.remove(parameters.getName())) {
    // Only build a Name LSA if a name was actually removed
    m_lsdb.buildAndInstallOwnNameLsa();
  }
}

bool
PrefixUpdateProcessor::validateParameters(const ndn::nfd::ControlCommand& command,
                                          const ndn::nfd::ControlParameters& parameters)
{
  try {
    command.validateRequest(parameters);
  }
  catch (const ndn::nfd::ControlCommand::ArgumentError&) {
    return false;
  }

  return true;
}

void
PrefixUpdateProcessor::sendNack(const ndn::Interest& request)
{
  ndn::MetaInfo metaInfo;
  metaInfo.setType(ndn::tlv::ContentType_Nack);

  std::shared_ptr<ndn::Data> responseData = std::make_shared<ndn::Data>(request.getName());
  responseData->setMetaInfo(metaInfo);

  m_keyChain.sign(*responseData);
  m_face.put(*responseData);
}

void
PrefixUpdateProcessor::sendResponse(const std::shared_ptr<const ndn::Interest>& request,
                                    uint32_t code,
                                    const std::string& text)
{
  if (request == nullptr) {
    return;
  }

  ndn::nfd::ControlResponse response(code, text);
  const ndn::Block& encodedControl = response.wireEncode();

  std::shared_ptr<ndn::Data> responseData = std::make_shared<ndn::Data>(request->getName());
  responseData->setContent(encodedControl);

  m_keyChain.sign(*responseData);
  m_face.put(*responseData);
}

} // namespace update
} // namespace nlsr
