/* -*- 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 "dataset-interest-handler.hpp"
#include "nlsr.hpp"
#include "tlv/lsdb-status.hpp"
#include "logger.hpp"

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

namespace nlsr {

INIT_LOGGER(DatasetInterestHandler);

const ndn::PartialName ADJACENCIES_DATASET = ndn::PartialName("lsdb/adjacencies");
const ndn::PartialName COORDINATES_DATASET = ndn::PartialName("lsdb/coordinates");
const ndn::PartialName NAMES_DATASET = ndn::PartialName("lsdb/names");
const ndn::PartialName RT_DATASET = ndn::PartialName("routing-table");

DatasetInterestHandler::DatasetInterestHandler(const Lsdb& lsdb,
                                               const RoutingTable& rt,
                                               ndn::mgmt::Dispatcher& dispatcher,
                                               const ndn::Face& face,
                                               const ndn::KeyChain& keyChain)
  : m_lsdb(lsdb)
  , m_dispatcher(dispatcher)
  , m_routingTableEntries(rt.getRoutingTableEntry())
  , m_dryRoutingTableEntries(rt.getDryRoutingTableEntry())
{
  setDispatcher(m_dispatcher);
}

void
DatasetInterestHandler::setDispatcher(ndn::mgmt::Dispatcher& dispatcher)
{
  dispatcher.addStatusDataset(ADJACENCIES_DATASET,
    ndn::mgmt::makeAcceptAllAuthorization(),
    std::bind(&DatasetInterestHandler::publishAdjStatus, this, _1, _2, _3));
  dispatcher.addStatusDataset(COORDINATES_DATASET,
    ndn::mgmt::makeAcceptAllAuthorization(),
    std::bind(&DatasetInterestHandler::publishCoordinateStatus, this, _1, _2, _3));
  dispatcher.addStatusDataset(NAMES_DATASET,
    ndn::mgmt::makeAcceptAllAuthorization(),
    std::bind(&DatasetInterestHandler::publishNameStatus, this, _1, _2, _3));
  dispatcher.addStatusDataset(RT_DATASET,
    ndn::mgmt::makeAcceptAllAuthorization(),
    std::bind(&DatasetInterestHandler::publishRtStatus, this, _1, _2, _3));
}

void
DatasetInterestHandler::publishAdjStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
                                         ndn::mgmt::StatusDatasetContext& context)
{
  NLSR_LOG_DEBUG("Received interest:  " << interest);

  auto lsaRange = std::make_pair<std::list<AdjLsa>::const_iterator,
                                 std::list<AdjLsa>::const_iterator>(
    m_lsdb.getAdjLsdb().cbegin(), m_lsdb.getAdjLsdb().cend());
  for (auto lsa = lsaRange.first; lsa != lsaRange.second; lsa++) {
    tlv::AdjacencyLsa tlvLsa;
    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(*lsa);
    tlvLsa.setLsaInfo(*tlvLsaInfo);

    for (const Adjacent& adj : lsa->getAdl().getAdjList()) {
      tlv::Adjacency tlvAdj;
      tlvAdj.setName(adj.getName());
      tlvAdj.setUri(adj.getFaceUri().toString());
      tlvAdj.setCost(adj.getLinkCost());
      tlvLsa.addAdjacency(tlvAdj);
    }
    const ndn::Block& wire = tlvLsa.wireEncode();
    context.append(wire);
  }
  context.end();
}

void
DatasetInterestHandler::publishCoordinateStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
                                                ndn::mgmt::StatusDatasetContext& context)
{
  auto lsaRange = std::make_pair<std::list<CoordinateLsa>::const_iterator,
                                 std::list<CoordinateLsa>::const_iterator>(
    m_lsdb.getCoordinateLsdb().cbegin(), m_lsdb.getCoordinateLsdb().cend());

  NLSR_LOG_DEBUG("Received interest:  " << interest);
  for (auto lsa = lsaRange.first; lsa != lsaRange.second; lsa++) {
    tlv::CoordinateLsa tlvLsa;
    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(*lsa);
    tlvLsa.setLsaInfo(*tlvLsaInfo);

    tlvLsa.setHyperbolicRadius(lsa->getCorRadius());
    tlvLsa.setHyperbolicAngle(lsa->getCorTheta());

    const ndn::Block& wire = tlvLsa.wireEncode();
    context.append(wire);
  }
  context.end();
}

void
DatasetInterestHandler::publishNameStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
                                          ndn::mgmt::StatusDatasetContext& context)
{
  auto lsaRange = std::make_pair<std::list<NameLsa>::const_iterator, std::list<NameLsa>::const_iterator>(
    m_lsdb.getNameLsdb().cbegin(), m_lsdb.getNameLsdb().cend());
  NLSR_LOG_DEBUG("Received interest:  " << interest);
  for (auto lsa = lsaRange.first; lsa != lsaRange.second; lsa++) {
    tlv::NameLsa tlvLsa;

    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(*lsa);
    tlvLsa.setLsaInfo(*tlvLsaInfo);

    for (const ndn::Name& name : lsa->getNpl().getNames()) {
      tlvLsa.addName(name);
    }

    const ndn::Block& wire = tlvLsa.wireEncode();
    context.append(wire);
  }
  context.end();
}

void
DatasetInterestHandler::publishRtStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
                                        ndn::mgmt::StatusDatasetContext& context)
{
  NLSR_LOG_DEBUG("Received interest for routing table:  " << interest);
  tlv::RoutingTable tlvRoutingTable;

  for (const auto& rte : m_routingTableEntries) {
    std::shared_ptr<tlv::Destination> tlvDes = tlv::makeDes(rte);
    tlvRoutingTable.setDestination(*tlvDes);

    for (const auto& nh : rte.getNexthopList().getNextHops()) {
      tlv::NextHop tlvNexthop;
      tlvNexthop.setUri(nh.getConnectingFaceUri());
      tlvNexthop.setCost(nh.getRouteCost());
      tlvRoutingTable.addNexthops(tlvNexthop);
    }

    const ndn::Block& wire = tlvRoutingTable.wireEncode();
    context.append(wire);
  }
  if (!m_dryRoutingTableEntries.empty()) {
    for (const auto& dry_rte : m_dryRoutingTableEntries ) {
        std::shared_ptr<tlv::Destination> tlvDes = tlv::makeDes(dry_rte);
        tlvRoutingTable.setDestination(*tlvDes);

        for (const auto& nh : dry_rte.getNexthopList().getNextHops()) {
          tlv::NextHop tlvNexthop;
          tlvNexthop.setUri(nh.getConnectingFaceUri());
          tlvNexthop.setCost(nh.getRouteCost());
          tlvRoutingTable.addNexthops(tlvNexthop);
        }
        const ndn::Block& wire = tlvRoutingTable.wireEncode();
        context.append(wire);
      }
  }

  context.end();
}

template<> std::list<tlv::AdjacencyLsa>
getTlvLsas<tlv::AdjacencyLsa>(const Lsdb& lsdb)
{
  std::list<tlv::AdjacencyLsa> lsas;

  auto lsaRange = std::make_pair<std::list<AdjLsa>::const_iterator,
                                 std::list<AdjLsa>::const_iterator>(
    lsdb.getAdjLsdb().cbegin(), lsdb.getAdjLsdb().cend());
  for (auto lsa = lsaRange.first; lsa != lsaRange.second; lsa++) {
    tlv::AdjacencyLsa tlvLsa;

    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(*lsa);
    tlvLsa.setLsaInfo(*tlvLsaInfo);

    for (const Adjacent& adj : lsa->getAdl().getAdjList()) {
      tlv::Adjacency tlvAdj;
      tlvAdj.setName(adj.getName());
      tlvAdj.setUri(adj.getFaceUri().toString());
      tlvAdj.setCost(adj.getLinkCost());
      tlvLsa.addAdjacency(tlvAdj);
    }

    lsas.push_back(tlvLsa);
  }

  return lsas;

}

template<> std::list<tlv::CoordinateLsa>
getTlvLsas<tlv::CoordinateLsa>(const Lsdb& lsdb)
{
  std::list<tlv::CoordinateLsa> lsas;

  auto lsaRange = std::make_pair<std::list<CoordinateLsa>::const_iterator,
                                 std::list<CoordinateLsa>::const_iterator>(
    lsdb.getCoordinateLsdb().cbegin(), lsdb.getCoordinateLsdb().cend());

  for (auto lsa = lsaRange.first; lsa != lsaRange.second; lsa++) {
    tlv::CoordinateLsa tlvLsa;

    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(*lsa);
    tlvLsa.setLsaInfo(*tlvLsaInfo);

    tlvLsa.setHyperbolicRadius(lsa->getCorRadius());
    tlvLsa.setHyperbolicAngle(lsa->getCorTheta());

    lsas.push_back(tlvLsa);
  }

  return lsas;

}

template<> std::list<tlv::NameLsa>
getTlvLsas<tlv::NameLsa>(const Lsdb& lsdb)
{
  std::list<tlv::NameLsa> lsas;

  auto lsaRange = std::make_pair<std::list<NameLsa>::const_iterator,
                                 std::list<NameLsa>::const_iterator>(
    lsdb.getNameLsdb().cbegin(), lsdb.getNameLsdb().cend());
  for (auto lsa = lsaRange.first; lsa != lsaRange.second; lsa++) {
    tlv::NameLsa tlvLsa;

    std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(*lsa);
    tlvLsa.setLsaInfo(*tlvLsaInfo);

    for (const ndn::Name& name : lsa->getNpl().getNames()) {
      tlvLsa.addName(name);
    }

    lsas.push_back(tlvLsa);
  }

  return lsas;

}

} // namespace nlsr
