/* -*- 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 "common.hpp"
#include "rib-manager.hpp"
#include "core/config-file.hpp"
#include "core/logger.hpp"

namespace nfd {
namespace rib {

NFD_LOG_INIT("NRD");

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

class Nrd : noncopyable
{
public:
  class IgnoreNfdAndLogSections
  {
  public:
    void
    operator()(const std::string& filename,
               const std::string& sectionName,
               const ConfigSection& section,
               bool isDryRun)
    {
      // Ignore "log" and sections belonging to NFD,
      // but raise an error if we're missing a handler for an "rib_" section.

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

  void
  initialize(const std::string& configFile)
  {
    initializeLogging(configFile);

    m_ribManager = make_shared<RibManager>();

    ConfigFile config((IgnoreNfdAndLogSections()));
    m_ribManager->setConfigFile(config);

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

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

  void
  initializeLogging(const std::string& configFile)
  {
    ConfigFile config(&ConfigFile::ignoreUnknownSection);
    LoggerFactory::getInstance().setConfigFile(config);

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

  boost::asio::io_service&
  getIoService()
  {
    return m_ribManager->getIoService();
  }

  static void
  printUsage(std::ostream& os, const std::string& programName)
  {
    os << "Usage: \n"
       << "  " << programName << " [options]\n"
       << "\n"
       << "Run NRD daemon\n"
       << "\n"
       << "Options:\n"
       << "  [--help]   - print this help message\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.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 },
        { 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;
            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)
      {
        getIoService().stop();
        NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
      }
    else
      {
        /// \todo May be try to reload config file
        signalSet.async_wait(bind(&Nrd::terminate, this, _1, _2,
                                  boost::ref(signalSet)));
      }
  }

private:
  shared_ptr<RibManager> m_ribManager;
};

} // namespace rib
} // namespace nfd

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

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

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

  Nrd nrdInstance;

  try {
    nrdInstance.initialize(options.config);
  }
  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;
  }

  boost::asio::signal_set signalSet(nrdInstance.getIoService());
  signalSet.add(SIGINT);
  signalSet.add(SIGTERM);
  signalSet.add(SIGHUP);
  signalSet.add(SIGUSR1);
  signalSet.add(SIGUSR2);
  signalSet.async_wait(bind(&Nrd::terminate, &nrdInstance, _1, _2,
                            boost::ref(signalSet)));

  try {
    nrdInstance.getIoService().run();
  }
  catch (std::exception& e) {
    NFD_LOG_FATAL(e.what());
    return 3;
  }

  return 0;
}
