/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2016,  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 "core/version.hpp"

#include "multicast-discovery.hpp"
#include "guess-from-search-domains.hpp"
#include "guess-from-identity-name.hpp"

#include <ndn-cxx/util/network-monitor.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include <ndn-cxx/util/scheduler-scoped-event-id.hpp>

#include <boost/noncopyable.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

namespace po = boost::program_options;

namespace ndn {
namespace tools {
namespace autoconfig {
// ndn-autoconfig is an NDN tool not an NFD tool, so it uses ndn::tools::autoconfig namespace.
// It lives in NFD repository because nfd-start can automatically start ndn-autoconfig in daemon mode.

class NdnAutoconfig : boost::noncopyable
{
public:
  class Error : public std::runtime_error
  {
  public:
    explicit
    Error(const std::string& what)
      : std::runtime_error(what)
    {
    }
  };

  explicit
  NdnAutoconfig(bool isDaemonMode)
    : m_face(m_io)
    , m_scheduler(m_io)
    , m_startStagesEvent(m_scheduler)
    , m_isDaemonMode(isDaemonMode)
    , m_terminationSignalSet(m_io)
    , m_stage1(m_face, m_keyChain,
               [&] (const std::string& errorMessage) {
                 std::cerr << "Stage 1 failed: " << errorMessage << std::endl;
                 m_stage2.start();
               })
    , m_stage2(m_face, m_keyChain,
               [&] (const std::string& errorMessage) {
                 std::cerr << "Stage 2 failed: " << errorMessage << std::endl;
                 m_stage3.start();
               })
    , m_stage3(m_face, m_keyChain,
               [&] (const std::string& errorMessage) {
                 std::cerr << "Stage 3 failed: " << errorMessage << std::endl;
                 if (!m_isDaemonMode)
                   BOOST_THROW_EXCEPTION(Error("No more stages, automatic discovery failed"));
                 else
                   std::cerr << "No more stages, automatic discovery failed" << std::endl;
               })
  {
    if (m_isDaemonMode) {
      m_networkMonitor.reset(new ndn::util::NetworkMonitor(m_io));
      m_networkMonitor->onNetworkStateChanged.connect([this] {
          // delay stages, so if multiple events are triggered in short sequence,
          // only one auto-detection procedure is triggered
          m_startStagesEvent = m_scheduler.scheduleEvent(time::seconds(5),
                                                         bind(&NdnAutoconfig::startStages, this));
        });
    }

    // Delay a little bit
    m_startStagesEvent = m_scheduler.scheduleEvent(time::milliseconds(100),
                                                   bind(&NdnAutoconfig::startStages, this));
  }

  void
  run()
  {
    if (m_isDaemonMode) {
      m_terminationSignalSet.add(SIGINT);
      m_terminationSignalSet.add(SIGTERM);
      m_terminationSignalSet.async_wait(bind(&NdnAutoconfig::terminate, this, _1, _2));
    }

    m_io.run();
  }

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

    m_io.stop();
  }

  static void
  usage(std::ostream& os,
        const po::options_description& optionDescription,
        const char* programName)
  {
    os << "Usage:\n"
       << "  " << programName << " [options]\n"
       << "\n";
    os << optionDescription;
  }

private:
  void
  startStages()
  {
    m_stage1.start();
    if (m_isDaemonMode) {
      m_startStagesEvent = m_scheduler.scheduleEvent(time::hours(1),
                                                     bind(&NdnAutoconfig::startStages, this));
    }
  }

private:
  boost::asio::io_service m_io;
  Face m_face;
  KeyChain m_keyChain;
  unique_ptr<util::NetworkMonitor> m_networkMonitor;
  util::Scheduler m_scheduler;
  util::scheduler::ScopedEventId m_startStagesEvent;
  bool m_isDaemonMode;
  boost::asio::signal_set m_terminationSignalSet;

  MulticastDiscovery m_stage1;
  GuessFromSearchDomains m_stage2;
  GuessFromIdentityName m_stage3;
};

static int
main(int argc, char** argv)
{
  bool isDaemonMode = false;
  std::string configFile;

  po::options_description optionDescription("Options");
  optionDescription.add_options()
    ("help,h", "produce help message")
    ("daemon,d", po::bool_switch(&isDaemonMode)->default_value(isDaemonMode),
     "run in daemon mode, detecting network change events and re-running "
     "auto-discovery procedure.  In addition, the auto-discovery procedure "
     "is unconditionally re-run every hour.\n"
     "NOTE: if connection to NFD fails, the daemon will be terminated.")
    ("config,c", po::value<std::string>(&configFile), "configuration file. If `enabled = true` "
     "is not specified, no actions will be performed.")
    ("version,V", "show version and exit")
    ;

  po::variables_map options;
  try {
    po::store(po::parse_command_line(argc, argv, optionDescription), options);
    po::notify(options);
  }
  catch (const std::exception& e) {
    std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
    NdnAutoconfig::usage(std::cerr, optionDescription, argv[0]);
    return 1;
  }

  if (options.count("help")) {
    NdnAutoconfig::usage(std::cout, optionDescription, argv[0]);
    return 0;
  }

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

  // Enable (one-shot or daemon mode whenever config file is not specified)
  bool isEnabled = true;

  po::options_description configFileOptions;
  configFileOptions.add_options()
    ("enabled", po::value<bool>(&isEnabled))
    ;

  if (!configFile.empty()) {
    isEnabled = false; // Disable by default if config file is specified
    try {
      po::store(po::parse_config_file<char>(configFile.c_str(), configFileOptions), options);
      po::notify(options);
    }
    catch (const std::exception& e) {
      std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
      return 1;
    }
  }

  if (!isEnabled) {
    return 0;
  }

  try {
    NdnAutoconfig autoConfigInstance(isDaemonMode);
    autoConfigInstance.run();
  }
  catch (const std::exception& error) {
    std::cerr << "ERROR: " << error.what() << std::endl;
    return 1;
  }
  return 0;
}

} // namespace autoconfig
} // namespace tools
} // namespace ndn

int
main(int argc, char** argv)
{
  return ndn::tools::autoconfig::main(argc, argv);
}
