/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  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 <getopt.h>
#include <boost/filesystem.hpp>

#include "version.hpp"
#include "core/logger.hpp"
#include "core/global-io.hpp"
#include "core/privilege-helper.hpp"
#include "fw/forwarder.hpp"
#include "mgmt/internal-face.hpp"
#include "mgmt/fib-manager.hpp"
#include "mgmt/face-manager.hpp"
#include "mgmt/strategy-choice-manager.hpp"
#include "mgmt/status-server.hpp"
#include "core/config-file.hpp"
#include "mgmt/general-config-section.hpp"
#include "mgmt/tables-config-section.hpp"

namespace nfd {

NFD_LOG_INIT("NFD");

struct ProgramOptions
{
  bool showUsage;
  bool showVersion;
  bool showModules;
  std::string config;
};

class Nfd : noncopyable
{
public:
  explicit
  Nfd(const std::string& configFile)
    : m_configFile(configFile)
    , m_originalStreamBuf(0)
  {
  }

  ~Nfd()
  {
    if (static_cast<bool>(m_originalStreamBuf)) {
      std::clog.rdbuf(m_originalStreamBuf);
    }
  }

  void
  initialize()
  {
    initializeLogging();

    m_forwarder = make_shared<Forwarder>();

    initializeManagement();

    PrivilegeHelper::drop();
  }


  void
  initializeLogging()
  {
    ConfigFile config(&ConfigFile::ignoreUnknownSection);
    LoggerFactory::getInstance().setConfigFile(config);

    config.parse(m_configFile, true);
    config.parse(m_configFile, false);
  }

  class IgnoreRibAndLogSections
  {
  public:
    void
    operator()(const std::string& filename,
               const std::string& sectionName,
               const ConfigSection& section,
               bool isDryRun)

    {
      // Ignore "log" and sections beginning with "rib_" (intended for rib manager),
      // but raise an error if we're missing a handler for an NFD section.

      if (sectionName.find("rib") == 0 || sectionName == "log")
        {
          // do nothing
        }
      else
        {
          // missing NFD section
          ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
        }
    }
  };

  void
  initializeManagement()
  {
    m_internalFace = make_shared<InternalFace>();

    m_fibManager = make_shared<FibManager>(ref(m_forwarder->getFib()),
                                           bind(&Forwarder::getFace, m_forwarder.get(), _1),
                                           m_internalFace);

    m_faceManager = make_shared<FaceManager>(ref(m_forwarder->getFaceTable()),
                                             m_internalFace);

    m_strategyChoiceManager =
      make_shared<StrategyChoiceManager>(ref(m_forwarder->getStrategyChoice()),
                                         m_internalFace);

    m_statusServer = make_shared<StatusServer>(m_internalFace,
                                               ref(*m_forwarder));

    ConfigFile config((IgnoreRibAndLogSections()));

    general::setConfigFile(config);

    TablesConfigSection tablesConfig(m_forwarder->getCs(),
                                     m_forwarder->getPit(),
                                     m_forwarder->getFib(),
                                     m_forwarder->getStrategyChoice(),
                                     m_forwarder->getMeasurements());

    tablesConfig.setConfigFile(config);

    m_internalFace->getValidator().setConfigFile(config);

    m_forwarder->addFace(m_internalFace);

    m_faceManager->setConfigFile(config);

    // parse config file
    config.parse(m_configFile, true);
    config.parse(m_configFile, false);

    // add FIB entry for NFD Management Protocol
    shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
    entry->addNextHop(m_internalFace, 0);
  }

  static void
  printUsage(std::ostream& os, const std::string& programName)
  {
    os << "Usage: \n"
       << "  " << programName << " [options]\n"
       << "\n"
       << "Run NFD forwarding daemon\n"
       << "\n"
       << "Options:\n"
       << "  [--help]    - print this help message\n"
       << "  [--version] - print version and exit\n"
       << "  [--modules] - list available logging modules\n"
       << "  [--config /path/to/nfd.conf] - path to configuration file "
       << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
      ;
  }

  static void
  printModules(std::ostream& os)
  {
    using namespace std;

    os << "Available logging modules: \n";

    list<string> modules(LoggerFactory::getInstance().getModules());
    for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
      {
        os << *i << "\n";
      }
  }

  static bool
  parseCommandLine(int argc, char** argv, ProgramOptions& options)
  {
    options.showUsage = false;
    options.showVersion = false;
    options.showModules = false;
    options.config = DEFAULT_CONFIG_FILE;

    while (true) {
      int optionIndex = 0;
      static ::option longOptions[] = {
        { "help"   , no_argument      , 0, 0 },
        { "modules", no_argument      , 0, 0 },
        { "config" , required_argument, 0, 0 },
        { "version", no_argument      , 0, 0 },
        { 0        , 0                , 0, 0 }
      };
      int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
      if (c == -1)
        break;

      switch (c) {
      case 0:
        switch (optionIndex) {
        case 0: // help
          options.showUsage = true;
          break;
        case 1: // modules
          options.showModules = true;
          break;
        case 2: // config
          options.config = ::optarg;
          break;
        case 3: // version
          options.showVersion = true;
          break;
        default:
          return false;
        }
        break;
      }
    }
    return true;
  }

  void
  terminate(const boost::system::error_code& error,
            int signalNo,
            boost::asio::signal_set& signalSet)
  {
    if (error)
      return;

    if (signalNo == SIGINT ||
        signalNo == SIGTERM)
      {
        getGlobalIoService().stop();
        NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
      }
    else
      {
        signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2, ref(signalSet)));
      }
  }

  void
  reload(const boost::system::error_code& error,
         int signalNo,
         boost::asio::signal_set& signalSet)
  {
    if (error)
      return;

    NFD_LOG_INFO("Caught signal '" << strsignal(signalNo));

    ////////////////////////
    // Reload config file //
    ////////////////////////

    // Logging
    initializeLogging();
    /// \todo Reopen log file

    // Other stuff
    ConfigFile config((IgnoreRibAndLogSections()));

    general::setConfigFile(config);

    TablesConfigSection tablesConfig(m_forwarder->getCs(),
                                     m_forwarder->getPit(),
                                     m_forwarder->getFib(),
                                     m_forwarder->getStrategyChoice(),
                                     m_forwarder->getMeasurements());

    tablesConfig.setConfigFile(config);

    m_internalFace->getValidator().setConfigFile(config);
    m_faceManager->setConfigFile(config);

    config.parse(m_configFile, false);

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

    signalSet.async_wait(bind(&Nfd::reload, this, _1, _2, ref(signalSet)));
  }

private:
  std::string m_configFile;

  shared_ptr<Forwarder> m_forwarder;

  shared_ptr<InternalFace>          m_internalFace;
  shared_ptr<FibManager>            m_fibManager;
  shared_ptr<FaceManager>           m_faceManager;
  shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
  shared_ptr<StatusServer>          m_statusServer;

  shared_ptr<std::ofstream>         m_logFile;
  std::basic_streambuf<char>*       m_originalStreamBuf;
};

} // namespace nfd

int
main(int argc, char** argv)
{
  using namespace nfd;

  ProgramOptions options;
  bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
  if (!isCommandLineValid) {
    Nfd::printUsage(std::cerr, argv[0]);
    return 1;
  }

  if (options.showUsage) {
    Nfd::printUsage(std::cout, argv[0]);
    return 0;
  }

  if (options.showVersion) {
    std::cout << NFD_VERSION_BUILD_STRING << std::endl;
    return 0;
  }

  if (options.showModules) {
    Nfd::printModules(std::cout);
    return 0;
  }

  Nfd nfdInstance(options.config);

  try {
    nfdInstance.initialize();
  }
  catch (boost::filesystem::filesystem_error& e) {
    if (e.code() == boost::system::errc::permission_denied) {
      NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
                    argv[0] << " should be run as superuser");
    }
    else {
      NFD_LOG_FATAL(e.what());
    }
    return 1;
  }
  catch (const std::exception& e) {
    NFD_LOG_FATAL(e.what());
    return 2;
  }
  catch (const PrivilegeHelper::Error& e) {
    // PrivilegeHelper::Errors do not inherit from std::exception
    // and represent seteuid/gid failures

    NFD_LOG_FATAL(e.what());
    return 3;
  }

  boost::asio::signal_set terminationSignalSet(getGlobalIoService());
  terminationSignalSet.add(SIGINT);
  terminationSignalSet.add(SIGTERM);
  terminationSignalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
                                       ref(terminationSignalSet)));

  boost::asio::signal_set reloadSignalSet(getGlobalIoService());
  reloadSignalSet.add(SIGHUP);
  reloadSignalSet.async_wait(bind(&Nfd::reload, &nfdInstance, _1, _2,
                                  ref(reloadSignalSet)));

  try {
    getGlobalIoService().run();
  }
  catch (const std::exception& e) {
    NFD_LOG_FATAL(e.what());
    return 4;
  }
  catch (const PrivilegeHelper::Error& e) {
    NFD_LOG_FATAL(e.what());
    return 5;
  }

  return 0;
}
