/* -*- 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 "nlsrc.hpp"

#include "version.hpp"
#include "src/publisher/lsdb-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 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"
    "       status\n"
    "           display NLSR status\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()
{
  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));

  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 == "status") {
    if (nOptions != 0) {
      return false;
    }

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

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

  ndn::util::SegmentFetcher::fetch(m_face,
                                   interest,
                                   m_validator,
                                   std::bind(&Nlsrc::onFetchSuccess<T>,
                                             this, _1, recordLsa),
                                   std::bind(&Nlsrc::onTimeout, this, _1, _2));
}

template <class T>
void
Nlsrc::onFetchSuccess(const ndn::ConstBufferPtr& data,
                      const std::function<void(const T&)>& recordLsa)
{
  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 lsa(block);
    recordLsa(lsa);
  }

  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 = getRouter(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 = getRouter(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 = getRouter(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::printLsdb()
{
  std::cout << "NLSR Status" << std::endl;
  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;
    }
  }
}

Nlsrc::Router&
Nlsrc::getRouter(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;
}
