/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2018,  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/face.hpp>
#include <ndn-cxx/data.hpp>
#include <ndn-cxx/interest.hpp>
#include <ndn-cxx/encoding/block.hpp>
#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
#include <ndn-cxx/mgmt/nfd/control-response.hpp>
#include <ndn-cxx/util/segment-fetcher.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/security/command-interest-signer.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;

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"
    "       withdraw name\n"
    "           remove a name prefix advertised through NLSR"
    << 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 != 1) {
      return false;
    }

    advertiseName();
    return true;
  }
  else if (command == "withdraw") {
    if (nOptions != 1) {
      return false;
    }

    withdrawName();
    return true;
  }
  else if ((command == "lsdb")|| (command == "routing")||(command == "status")) {
    if (nOptions != 0) {
      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[0];
  ndn::Name::Component verb("advertise");
  std::string info = "(Advertise: " + name.toUri() + ")";

  sendNamePrefixUpdate(name, verb, info);
}

void
Nlsrc::withdrawName()
{
  ndn::Name name = commandLineArguments[0];
  ndn::Name::Component verb("withdraw");
  std::string info = "(Withdraw: " + name.toUri() + ")";

  sendNamePrefixUpdate(name, verb, info);
}

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

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

  ndn::security::CommandInterestSigner cis(m_keyChain);

  ndn::Interest commandInterest =
    cis.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) {
    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::tlv::AdjacencyLsa>(nlsr::dataset::ADJACENCY_COMPONENT,
                                         std::bind(&Nlsrc::recordAdjacencyLsa, this, _1));
}

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

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

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

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

  ndn::Interest interest(command);

  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));
}

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

  ndn::Interest interest(command);

  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;
}

std::string
Nlsrc::getLsaInfoString(const nlsr::tlv::LsaInfo& info)
{
  std::ostringstream os;
  os << "      info=" << info;

  return os.str();
}

void
Nlsrc::recordAdjacencyLsa(const nlsr::tlv::AdjacencyLsa& lsa)
{
  Router& router = getRouterLsdb(lsa.getLsaInfo());

  std::ostringstream os;
  os << "    AdjacencyLsa:" << std::endl;

  os << getLsaInfoString(lsa.getLsaInfo()) << std::endl;

  for (const auto& adjacency : lsa.getAdjacencies()) {
    os << "      adjacency=" << adjacency << std::endl;
  }

  router.adjacencyLsaString = os.str();
}

void
Nlsrc::recordCoordinateLsa(const nlsr::tlv::CoordinateLsa& lsa)
{
  Router& router = getRouterLsdb(lsa.getLsaInfo());

  std::ostringstream os;
  os << "    Coordinate LSA:" << std::endl;

  os << getLsaInfoString(lsa.getLsaInfo()) << std::endl;

  int i = 0;
  for (auto const& value: lsa.getHyperbolicAngle()) {
    os << "    Hyp Angle " << i++ << ": "<< value << " ";
  }
  os << "\n   radius=" << lsa.getHyperbolicRadius() << std::endl;

  router.coordinateLsaString = os.str();
}

void
Nlsrc::recordNameLsa(const nlsr::tlv::NameLsa& lsa)
{
  Router& router = getRouterLsdb(lsa.getLsaInfo());

  std::ostringstream os;
  os << "    Name LSA:" << std::endl;

  os << getLsaInfoString(lsa.getLsaInfo()) << std::endl;

  for (const auto& name : lsa.getNames()) {
    os << "      name=" << name << std::endl;
  }

  router.nameLsaString = os.str();
}

void
Nlsrc::recordRtable(const nlsr::tlv::RoutingTableStatus& rts)
{
  std::ostringstream os;
  for (const auto& rt : rts.getRoutingtable()) {
    os << rt << std::endl;
  }
  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 << "Routing Table" << std::endl;
    std::cout << m_rtString << std::endl;
  }
  else {
    std::cout << "Routing Table is not calculated yet" << std::endl;
  }
}

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

Nlsrc::Router&
Nlsrc::getRouterLsdb(const nlsr::tlv::LsaInfo& info)
{
  const ndn::Name& originRouterName = info.getOriginRouter();

  const auto& pair =
    m_routers.insert(std::make_pair(originRouterName, Router()));

  return pair.first->second;
}

} // 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 = 2; // 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;
}
