/* -*- 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/global-io.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);
  }

  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)
      {
        getGlobalIoService().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(nfd::getGlobalIoService());
  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 {
    nfd::getGlobalIoService().run();
  }
  catch (std::exception& e) {
    NFD_LOG_FATAL(e.what());
    return 3;
  }

  return 0;
}
