/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2015-2019, Arizona Board of Regents.
 *
 * This file is part of ndn-tools (Named Data Networking Essential Tools).
 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
 *
 * ndn-tools 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.
 *
 * ndn-tools 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
 * ndn-tools, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Eric Newberry <enewberry@email.arizona.edu>
 * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
 */

#include "core/common.hpp"
#include "core/version.hpp"

#include "ping-server.hpp"
#include "tracer.hpp"

namespace ndn {
namespace ping {
namespace server {

namespace po = boost::program_options;

class Runner : noncopyable
{
public:
  explicit
  Runner(const Options& options)
    : m_options(options)
    , m_pingServer(m_face, m_keyChain, options)
    , m_tracer(m_pingServer, options)
    , m_signalSet(m_face.getIoService(), SIGINT)
  {
    m_pingServer.afterFinish.connect([this] {
      m_pingServer.stop();
      m_signalSet.cancel();
    });

    m_signalSet.async_wait([this] (const auto& ec, auto) {
      if (ec != boost::asio::error::operation_aborted) {
        m_pingServer.stop();
      }
    });
  }

  int
  run()
  {
    std::cout << "PING SERVER " << m_options.prefix << std::endl;

    try {
      m_pingServer.start();
      m_face.processEvents();
    }
    catch (const std::exception& e) {
      std::cerr << "ERROR: " << e.what() << std::endl;
      return 1;
    }

    std::cout << "\n--- " << m_options.prefix << " ping server statistics ---\n"
              << m_pingServer.getNPings() << " packets processed" << std::endl;
    return 0;
  }

private:
  const Options& m_options;

  Face m_face;
  KeyChain m_keyChain;
  PingServer m_pingServer;
  Tracer m_tracer;

  boost::asio::signal_set m_signalSet;
};

static void
usage(std::ostream& os, const std::string& programName, const po::options_description& options)
{
  os << "Usage: " << programName << " [options] <prefix>\n"
     << "\n"
     << "Starts a NDN ping server that responds to Interests under name ndn:<prefix>/ping\n"
     << "\n"
     << options;
}

static int
main(int argc, char* argv[])
{
  Options options;
  std::string prefix;
  auto nMaxPings = static_cast<std::make_signed_t<size_t>>(options.nMaxPings);
  auto payloadSize = static_cast<std::make_signed_t<size_t>>(options.payloadSize);

  po::options_description visibleDesc("Options");
  visibleDesc.add_options()
    ("help,h",      "print this help message and exit")
    ("freshness,x", po::value<time::milliseconds::rep>()->default_value(options.freshnessPeriod.count()),
                    "FreshnessPeriod of the ping response, in milliseconds")
    ("satisfy,p",   po::value(&nMaxPings)->default_value(nMaxPings),
                    "maximum number of pings to be satisfied (0=infinite)")
    ("size,s",      po::value(&payloadSize)->default_value(payloadSize),
                    "size of response payload")
    ("timestamp,t", po::bool_switch(&options.wantTimestamp),
                    "prepend a timestamp to each log message")
    ("quiet,q",     po::bool_switch(&options.wantQuiet),
                    "do not print a log message each time a ping packet is received")
    ("version,V",   "print program version and exit")
    ;

  po::options_description hiddenDesc;
  hiddenDesc.add_options()
    ("prefix", po::value<std::string>(&prefix));

  po::positional_options_description posDesc;
  posDesc.add("prefix", -1);

  po::options_description optDesc;
  optDesc.add(visibleDesc).add(hiddenDesc);

  po::variables_map vm;
  try {
    po::store(po::command_line_parser(argc, argv).options(optDesc).positional(posDesc).run(), vm);
    po::notify(vm);
  }
  catch (const po::error& e) {
    std::cerr << "ERROR: " << e.what() << "\n\n";
    usage(std::cerr, argv[0], visibleDesc);
    return 2;
  }
  catch (const boost::bad_any_cast& e) {
    std::cerr << "ERROR: " << e.what() << "\n\n";
    usage(std::cerr, argv[0], visibleDesc);
    return 2;
  }

  if (vm.count("help") > 0) {
    usage(std::cout, argv[0], visibleDesc);
    return 0;
  }

  if (vm.count("version") > 0) {
    std::cout << "ndnpingserver " << tools::VERSION << std::endl;
    return 0;
  }

  if (prefix.empty()) {
    std::cerr << "ERROR: no name prefix specified\n\n";
    usage(std::cerr, argv[0], visibleDesc);
    return 2;
  }
  options.prefix = prefix;

  options.freshnessPeriod = time::milliseconds(vm["freshness"].as<time::milliseconds::rep>());
  if (options.freshnessPeriod < 0_ms) {
    std::cerr << "ERROR: FreshnessPeriod cannot be negative" << std::endl;
    return 2;
  }

  if (nMaxPings < 0) {
    std::cerr << "ERROR: maximum number of pings to satisfy cannot be negative" << std::endl;
    return 2;
  }
  options.nMaxPings = static_cast<size_t>(nMaxPings);

  if (payloadSize < 0) {
    std::cerr << "ERROR: payload size cannot be negative" << std::endl;
    return 2;
  }
  options.payloadSize = static_cast<size_t>(payloadSize);

  return Runner(options).run();
}

} // namespace server
} // namespace ping
} // namespace ndn

int
main(int argc, char* argv[])
{
  return ndn::ping::server::main(argc, argv);
}
