/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2018,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "service.hpp"

#include "auto-prefix-propagator.hpp"
#include "fib-updater.hpp"
#include "rib-manager.hpp"
#include "readvertise/client-to-nlsr-readvertise-policy.hpp"
#include "readvertise/nfd-rib-readvertise-destination.hpp"
#include "readvertise/readvertise.hpp"

#include "core/global-io.hpp"

#include <boost/property_tree/info_parser.hpp>

#include <ndn-cxx/transport/tcp-transport.hpp>
#include <ndn-cxx/transport/unix-transport.hpp>

namespace nfd {
namespace rib {

static const std::string INTERNAL_CONFIG = "internal://nfd.conf";
static const Name READVERTISE_NLSR_PREFIX = "/localhost/nlsr";

Service* Service::s_instance = nullptr;

Service::Service(const std::string& configFile, ndn::KeyChain& keyChain)
  : m_configFile(configFile)
  , m_keyChain(keyChain)
{
  if (s_instance != nullptr) {
    BOOST_THROW_EXCEPTION(std::logic_error("RIB service cannot be instantiated more than once"));
  }
  if (&getGlobalIoService() != &getRibIoService()) {
    BOOST_THROW_EXCEPTION(std::logic_error("RIB service must run on RIB thread"));
  }
  s_instance = this;
}

Service::Service(const ConfigSection& configSection, ndn::KeyChain& keyChain)
  : m_configSection(configSection)
  , m_keyChain(keyChain)
{
  if (s_instance != nullptr) {
    BOOST_THROW_EXCEPTION(std::logic_error("RIB service cannot be instantiated more than once"));
  }
  if (&getGlobalIoService() != &getRibIoService()) {
    BOOST_THROW_EXCEPTION(std::logic_error("RIB service must run on RIB thread"));
  }
  s_instance = this;
}

Service::~Service()
{
  s_instance = nullptr;
}

Service&
Service::get()
{
  if (s_instance == nullptr) {
    BOOST_THROW_EXCEPTION(std::logic_error("RIB service is not instantiated"));
  }
  if (&getGlobalIoService() != &getRibIoService()) {
    BOOST_THROW_EXCEPTION(std::logic_error("Must get RIB service on RIB thread"));
  }
  return *s_instance;
}

void
Service::initialize()
{
  m_face = make_unique<ndn::Face>(getLocalNfdTransport(), getGlobalIoService(), m_keyChain);
  m_nfdController = make_unique<ndn::nfd::Controller>(*m_face, m_keyChain);
  m_fibUpdater = make_unique<FibUpdater>(m_rib, *m_nfdController);
  m_prefixPropagator = make_unique<AutoPrefixPropagator>(*m_nfdController, m_keyChain, m_rib);
  m_dispatcher = make_unique<ndn::mgmt::Dispatcher>(*m_face, m_keyChain);
  m_ribManager = make_unique<RibManager>(m_rib, *m_dispatcher, *m_face, *m_nfdController, *m_prefixPropagator);

  ConfigFile config([] (const std::string& filename, const std::string& sectionName,
                        const ConfigSection& section, bool isDryRun) {
      // Ignore sections belonging to NFD, but raise an error
      // if we're missing a handler for a "rib" section.
      if (sectionName == "rib") {
        ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
      }
    });
  m_ribManager->setConfigFile(config);

  // parse config file
  if (!m_configFile.empty()) {
    config.parse(m_configFile, true);
    config.parse(m_configFile, false);
  }
  else {
    config.parse(m_configSection, true, INTERNAL_CONFIG);
    config.parse(m_configSection, false, INTERNAL_CONFIG);
  }

  if (m_ribManager->wantAutoPrefixPropagator) {
    m_prefixPropagator->enable();
  }
  else {
    m_prefixPropagator->disable();
  }

  if (m_ribManager->wantReadvertiseToNlsr && m_readvertiseNlsr == nullptr) {
    m_readvertiseNlsr = make_unique<Readvertise>(
      m_rib,
      make_unique<ClientToNlsrReadvertisePolicy>(),
      make_unique<NfdRibReadvertiseDestination>(*m_nfdController, READVERTISE_NLSR_PREFIX, m_rib));
  }
  else if (!m_ribManager->wantReadvertiseToNlsr && m_readvertiseNlsr != nullptr) {
    m_readvertiseNlsr.reset();
  }

  m_ribManager->registerWithNfd();
  m_ribManager->enableLocalFields();
}

shared_ptr<ndn::Transport>
Service::getLocalNfdTransport()
{
  ConfigSection config;

  if (!m_configFile.empty()) {
    // Any format errors should have been caught already
    // If error is thrown at this point, it is development error
    boost::property_tree::read_info(m_configFile, config);
  }
  else {
    config = m_configSection;
  }

  if (config.get_child_optional("face_system.unix")) {
    // unix socket enabled

    auto socketPath = config.get<std::string>("face_system.unix.path", "/var/run/nfd.sock");
    // default socketPath should be the same as in UnixStreamFactory::processConfig

    return make_shared<ndn::UnixTransport>(socketPath);
  }
  else if (config.get_child_optional("face_system.tcp") &&
           config.get<std::string>("face_system.tcp.listen", "yes") == "yes") {
    // tcp is enabled

    auto port = config.get<std::string>("face_system.tcp.port", "6363");
    // default port should be the same as in TcpFactory::processConfig

    return make_shared<ndn::TcpTransport>("localhost", port);
  }
  else {
    BOOST_THROW_EXCEPTION(Error("No transport is available to communicate with NFD"));
  }
}

} // namespace rib
} // namespace nfd
