/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2021,  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 "nlsrc.hpp"

#include "version.hpp"
#include "src/publisher/dataset-interest-handler.hpp"

#include <ndn-cxx/data.hpp>
#include <ndn-cxx/encoding/block.hpp>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/interest.hpp>
#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
#include <ndn-cxx/mgmt/nfd/control-response.hpp>
#include <ndn-cxx/security/interest-signer.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>
#include <ndn-cxx/util/segment-fetcher.hpp>

#include <iostream>

namespace nlsrc {

const ndn::Name Nlsrc::LOCALHOST_PREFIX = ndn::Name("/localhost/nlsr");
const ndn::Name Nlsrc::LSDB_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("lsdb");
const ndn::Name Nlsrc::NAME_UPDATE_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("prefix-update");

const ndn::Name Nlsrc::RT_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("routing-table");

const uint32_t Nlsrc::ERROR_CODE_TIMEOUT = 10060;
const uint32_t Nlsrc::RESPONSE_CODE_SUCCESS = 200;
const uint32_t Nlsrc::RESPONSE_CODE_SAVE_OR_DELETE = 205;

Nlsrc::Nlsrc(ndn::Face& face)
  : m_face(face)
{
}

void
Nlsrc::printUsage()
{
  std::cout << "Usage:\n" << programName  << " [-h] [-V] COMMAND [<Command Options>]\n"
    "       -h print usage and exit\n"
    "       -V print version and exit\n"
    "\n"
    "   COMMAND can be one of the following:\n"
    "       lsdb\n"
    "           display NLSR lsdb status\n"
    "       routing\n"
    "           display routing table status\n"
    "       status\n"
    "           display all NLSR status (lsdb & routingtable)\n"
    "       advertise name\n"
    "           advertise a name prefix through NLSR\n"
    "       advertise name save\n"
    "           advertise and save the name prefix to the conf file\n"
    "       withdraw name\n"
    "           remove a name prefix advertised through NLSR\n"
    "       withdraw name delete\n"
    "           withdraw and delete the name prefix from the conf file"
    << std::endl;
}

void
Nlsrc::getStatus(const std::string& command)
{
  if (command == "lsdb") {
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::printLsdb, this));
  }
  else if (command == "routing") {
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::printRT, this));
  }
  else if(command == "status") {
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
    m_fetchSteps.push_back(std::bind(&Nlsrc::printAll, this));
  }
  runNextStep();
}

bool
Nlsrc::dispatch(const std::string& command)
{
  if (command == "advertise") {
    if (nOptions < 0) {
      return false;
    }
    else if (nOptions == 1) {
      std::string saveFlag = commandLineArguments[0];
      if (saveFlag != "save") {
        return false;
      }
    }

    advertiseName();
    return true;
  }
  else if (command == "withdraw") {
    if (nOptions < 0) {
      return false;
    }
    else if (nOptions == 1) {
      std::string saveFlag = commandLineArguments[0];
      if (saveFlag != "delete") {
        return false;
      }
    }

    withdrawName();
    return true;
  }
  else if ((command == "lsdb") || (command == "routing") || (command == "status")) {
    if (nOptions != -1) {
      return false;
    }
    commandString = command;

    getStatus(command);
    return true;
  }

  return false;
}

void
Nlsrc::runNextStep()
{
  if (m_fetchSteps.empty()) {
    return;
  }

  std::function<void()> nextStep = m_fetchSteps.front();
  m_fetchSteps.pop_front();

  nextStep();
}

void
Nlsrc::advertiseName()
{
  ndn::Name name = commandLineArguments[-1];

  bool saveFlag = false;
  std::string info = "(Advertise: " + name.toUri() + ")";
  if (commandLineArguments[0]) {
    saveFlag = true;
    info = "(Save: " + name.toUri() + ")";
  }
  ndn::Name::Component verb("advertise");
  sendNamePrefixUpdate(name, verb, info, saveFlag);
}

void
Nlsrc::withdrawName()
{
  ndn::Name name = commandLineArguments[-1];

  bool deleteFlag = false;
  std::string info = "(Withdraw: " + name.toUri() + ")";
  if (commandLineArguments[0]) {
    deleteFlag = true;
    info = "(Delete: " + name.toUri() + ")";
  }
  ndn::Name::Component verb("withdraw");
  sendNamePrefixUpdate(name, verb, info, deleteFlag);
}

void
Nlsrc::sendNamePrefixUpdate(const ndn::Name& name,
                            const ndn::Name::Component& verb,
                            const std::string& info,
                            bool flag)
{
  ndn::nfd::ControlParameters parameters;
  parameters.setName(name);
  if (flag) {
    parameters.setFlags(1);
  }

  ndn::Name commandName = NAME_UPDATE_PREFIX;
  commandName.append(verb);
  commandName.append(parameters.wireEncode());

  ndn::security::InterestSigner signer(m_keyChain);
  auto commandInterest = signer.makeCommandInterest(commandName,
                           ndn::security::signingByIdentity(m_keyChain.getPib().getDefaultIdentity()));
  commandInterest.setMustBeFresh(true);

  m_face.expressInterest(commandInterest,
                         std::bind(&Nlsrc::onControlResponse, this, info, _2),
                         std::bind(&Nlsrc::onTimeout, this, ERROR_CODE_TIMEOUT, "Nack"),
                         std::bind(&Nlsrc::onTimeout, this, ERROR_CODE_TIMEOUT, "Timeout"));
}

void
Nlsrc::onControlResponse(const std::string& info, const ndn::Data& data)
{
  if (data.getMetaInfo().getType() == ndn::tlv::ContentType_Nack) {
    std::cerr << "ERROR: Run-time advertise/withdraw disabled" << std::endl;
    return;
  }

  ndn::nfd::ControlResponse response;

  try {
    response.wireDecode(data.getContent().blockFromValue());
  }
  catch (const std::exception& e) {
    std::cerr << "ERROR: Control response decoding error" << std::endl;
    return;
  }

  uint32_t code = response.getCode();

  if (code != RESPONSE_CODE_SUCCESS && code != RESPONSE_CODE_SAVE_OR_DELETE) {

    std::cerr << response.getText() << std::endl;
    std::cerr << "Name prefix update error (code: " << code << ")" << std::endl;
    return;
  }

  std::cout << "Applied Name prefix update successfully: " << info << std::endl;
}

void
Nlsrc::fetchAdjacencyLsas()
{
  fetchFromLsdb<nlsr::AdjLsa>(nlsr::dataset::ADJACENCY_COMPONENT,
                              std::bind(&Nlsrc::recordLsa, this, _1));
}

void
Nlsrc::fetchCoordinateLsas()
{
  fetchFromLsdb<nlsr::CoordinateLsa>(nlsr::dataset::COORDINATE_COMPONENT,
                                     std::bind(&Nlsrc::recordLsa, this, _1));
}

void
Nlsrc::fetchNameLsas()
{
  fetchFromLsdb<nlsr::NameLsa>(nlsr::dataset::NAME_COMPONENT,
                               std::bind(&Nlsrc::recordLsa, this, _1));
}

void
Nlsrc::fetchRtables()
{
  fetchFromRt<nlsr::RoutingTableStatus>([this] (const auto& rts) { this->recordRtable(rts); });
}

template <class T>
void
Nlsrc::fetchFromLsdb(const ndn::Name::Component& datasetType,
                     const std::function<void(const T&)>& recordLsa)
{
  ndn::Interest interest(ndn::Name(LSDB_PREFIX).append(datasetType));

  auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest, m_validator);
  fetcher->onComplete.connect(std::bind(&Nlsrc::onFetchSuccess<T>, this, _1, recordLsa));
  fetcher->onError.connect(std::bind(&Nlsrc::onTimeout, this, _1, _2));
}

void
Nlsrc::recordLsa(const nlsr::Lsa& lsa)
{
  Router& router = m_routers.emplace(lsa.getOriginRouter(), Router()).first->second;

  if (lsa.getType() == nlsr::Lsa::Type::ADJACENCY) {
    router.adjacencyLsaString = lsa.toString();
  }
  else if (lsa.getType() == nlsr::Lsa::Type::COORDINATE) {
    router.coordinateLsaString = lsa.toString();
  }
  else if (lsa.getType() == nlsr::Lsa::Type::NAME) {
    router.nameLsaString = lsa.toString();
  }
}

template <class T>
void
Nlsrc::fetchFromRt(const std::function<void(const T&)>& recordDataset)
{
  ndn::Interest interest(RT_PREFIX);

  auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest, m_validator);
  fetcher->onComplete.connect(std::bind(&Nlsrc::onFetchSuccess<T>, this, _1, recordDataset));
  fetcher->onError.connect(std::bind(&Nlsrc::onTimeout, this, _1, _2));
}

template <class T>
void
Nlsrc::onFetchSuccess(const ndn::ConstBufferPtr& data,
                      const std::function<void(const T&)>& recordDataset)
{
  ndn::Block block;
  size_t offset = 0;

  while (offset < data->size()) {
    bool isOk = false;
    std::tie(isOk, block) = ndn::Block::fromBuffer(data, offset);

    if (!isOk) {
      std::cerr << "ERROR: cannot decode LSA TLV" << std::endl;
      break;
    }

    offset += block.size();

    T data(block);
    recordDataset(data);
  }

  runNextStep();
}

void
Nlsrc::onTimeout(uint32_t errorCode, const std::string& error)
{
  std::cerr << "Request timed out (code: " << errorCode
            << ", error: " << error << ")"  << std::endl;
}

void
Nlsrc::recordRtable(const nlsr::RoutingTableStatus& rts)
{
  std::ostringstream os;
  os << rts;
  m_rtString = os.str();
}

void
Nlsrc::printLsdb()
{
  std::cout << "LSDB:" << std::endl;

  for (const auto& item : m_routers) {
    std::cout << "  OriginRouter: " << item.first << std::endl;
    std::cout << std::endl;

    const Router& router = item.second;

    if (!router.adjacencyLsaString.empty()) {
      std::cout << router.adjacencyLsaString << std::endl;
    }

    if (!router.coordinateLsaString.empty()) {
      std::cout << router.coordinateLsaString << std::endl;
    }

    if (!router.nameLsaString.empty()) {
      std::cout << router.nameLsaString << std::endl;
    }
  }
}

void
Nlsrc::printRT()
{
  if (!m_rtString.empty()) {
    std::cout << m_rtString;
  }
  else {
    std::cout << "Routing Table is not calculated yet" << std::endl;
  }
}

void
Nlsrc::printAll()
{
  std::cout << "NLSR Status" << std::endl;
  printLsdb();
  printRT();
}

} // namespace nlsrc

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

int
main(int argc, char** argv)
{
  ndn::Face face;
  nlsrc::Nlsrc nlsrc(face);

  nlsrc.programName = argv[0];

  if (argc < 2) {
    nlsrc.printUsage();
    return 0;
  }

  int opt;
  while ((opt = ::getopt(argc, argv, "hV")) != -1) {
    switch (opt) {
    case 'h':
      nlsrc.printUsage();
      return 0;
    case 'V':
      std::cout << NLSR_VERSION_BUILD_STRING << std::endl;
      return 0;
    default:
      nlsrc.printUsage();
      return 1;
    }
  }

  if (argc == ::optind) {
    nlsrc.printUsage();
    return 1;
  }

  try {
    ::optind = 3; // Set ::optind to the command's index

    nlsrc.commandLineArguments = argv + ::optind;
    nlsrc.nOptions = argc - ::optind;

    // argv[1] points to the command, so pass it to the dispatch
    bool isOk = nlsrc.dispatch(argv[1]);
    if (!isOk) {
      nlsrc.printUsage();
      return 1;
    }

    face.processEvents();
  }
  catch (const std::exception& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    return 2;
  }
  return 0;
}
