/* -*- 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.Main");

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

class Nrd : noncopyable
{
public:
  void
  initialize(const std::string& configFile)
  {
    initializeLogging(configFile);

    m_ribManager = make_shared<RibManager>();

    ConfigFile config;
    m_ribManager->setConfigFile(config);
    config.addSectionHandler("log", bind(std::plus<int>(), 0, 0)); // no-op

    // 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;
    LoggerFactory::getInstance().setConfigFile(config);

    for (size_t i = 0; i < N_SUPPORTED_CONFIG_SECTIONS; ++i)
      {
        if (SUPPORTED_CONFIG_SECTIONS[i] != "log")
          {
            config.addSectionHandler(SUPPORTED_CONFIG_SECTIONS[i],
                                     bind(std::plus<int>(), 0, 0)); // no-op.
          }
      }

    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/nrd.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.config = DEFAULT_CONFIG_FILE;

    while (true) {
      int optionIndex = 0;
      static ::option longOptions[] = {
        { "help"   , 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: // 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();
        std::cout << "Caught signal '" << strsignal(signalNo) << "', exiting..." << std::endl;
      }
    else
      {
        /// \todo May be try to reload config file (at least security section)
        signalSet.async_wait(bind(&Nrd::terminate, this, _1, _2,
                                  boost::ref(signalSet)));
      }
  }

private:
  shared_ptr<RibManager> m_ribManager;

  static const std::string SUPPORTED_CONFIG_SECTIONS[];
  static const size_t      N_SUPPORTED_CONFIG_SECTIONS;
};

const std::string Nrd::SUPPORTED_CONFIG_SECTIONS[] =
  {
    "log",
    "security",
  };

const size_t Nrd::N_SUPPORTED_CONFIG_SECTIONS =
  sizeof(SUPPORTED_CONFIG_SECTIONS) / sizeof(std::string);

} // 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;
}
