/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2021,  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: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
 * @author: Eric Newberry <enewberry@email.arizona.edu>
 */

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

#include "ping.hpp"
#include "statistics-collector.hpp"
#include "tracer.hpp"

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

namespace ndn {
namespace ping {
namespace client {

class Runner : noncopyable
{
public:
  explicit
  Runner(const Options& options)
    : m_ping(m_face, options)
    , m_statisticsCollector(m_ping, options)
    , m_tracer(m_ping, options)
    , m_signalSetInt(m_face.getIoService(), SIGINT)
    , m_signalSetQuit(m_face.getIoService(), SIGQUIT)
  {
    m_signalSetInt.async_wait(bind(&Runner::afterIntSignal, this, _1));
    m_signalSetQuit.async_wait(bind(&Runner::afterQuitSignal, this, _1));

    m_ping.afterFinish.connect([this] {
        this->cancel();
      });
  }

  int
  run()
  {
    try {
      m_ping.start();
      m_face.processEvents();
    }
    catch (const std::exception& e) {
      m_tracer.onError(e.what());
      return 2;
    }

    Statistics statistics = m_statisticsCollector.computeStatistics();

    std::cout << statistics << std::endl;

    if (statistics.nReceived == statistics.nSent) {
      return 0;
    }
    else {
      return 1;
    }
  }

private:
  void
  cancel()
  {
    m_signalSetInt.cancel();
    m_signalSetQuit.cancel();
    m_ping.stop();
  }

  void
  afterIntSignal(const boost::system::error_code& errorCode)
  {
    if (errorCode == boost::asio::error::operation_aborted) {
      return;
    }

    cancel();
  }

  void
  afterQuitSignal(const boost::system::error_code& errorCode)
  {
    if (errorCode == boost::asio::error::operation_aborted) {
      return;
    }

    m_statisticsCollector.computeStatistics().printSummary(std::cout);
    m_signalSetQuit.async_wait(bind(&Runner::afterQuitSignal, this, _1));
  }

private:
  Face m_face;
  Ping m_ping;
  StatisticsCollector m_statisticsCollector;
  Tracer m_tracer;

  boost::asio::signal_set m_signalSetInt;
  boost::asio::signal_set m_signalSetQuit;
};

static time::milliseconds
getMinimumPingInterval()
{
  return time::milliseconds(1);
}

static time::milliseconds
getDefaultPingInterval()
{
  return time::milliseconds(1000);
}

static time::milliseconds
getDefaultPingTimeoutThreshold()
{
  return time::milliseconds(4000);
}

static void
usage(const boost::program_options::options_description& options)
{
  std::cout << "Usage: ndnping [options] ndn:/name/prefix\n"
               "\n"
               "Ping a NDN name prefix using Interests with name ndn:/name/prefix/ping/number.\n"
               "The numbers in the Interests are randomly generated unless specified.\n"
               "\n"
            << options;
  exit(2);
}

static int
main(int argc, char* argv[])
{
  Options options;
  options.shouldAllowStaleData = false;
  options.nPings = -1;
  options.interval = time::milliseconds(getDefaultPingInterval());
  options.timeout = time::milliseconds(getDefaultPingTimeoutThreshold());
  options.startSeq = 0;
  options.shouldGenerateRandomSeq = true;
  options.shouldPrintTimestamp = false;

  std::string identifier;

  namespace po = boost::program_options;

  po::options_description visibleOptDesc("Options");
  visibleOptDesc.add_options()
    ("help,h",      "print this message and exit")
    ("version,V",   "display version and exit")
    ("interval,i",  po::value<time::milliseconds::rep>()->default_value(getDefaultPingInterval().count()),
                    "ping interval, in milliseconds")
    ("timeout,o",   po::value<time::milliseconds::rep>()->default_value(getDefaultPingTimeoutThreshold().count()),
                    "ping timeout, in milliseconds")
    ("count,c",     po::value<int>(&options.nPings), "number of pings to send (default = no limit)")
    ("start,n",     po::value<uint64_t>(&options.startSeq),
                    "set the starting sequence number, the number is incremented by 1 after each Interest")
    ("identifier,p", po::value<std::string>(&identifier),
                     "add identifier to the Interest names before the sequence numbers to avoid conflicts")
    ("cache,a",     "allow routers to return stale Data from cache")
    ("timestamp,t", "print timestamp with messages")
  ;

  po::options_description hiddenOptDesc;
  hiddenOptDesc.add_options()
    ("prefix", po::value<std::string>(), "prefix to send pings to")
  ;

  po::options_description optDesc;
  optDesc.add(visibleOptDesc).add(hiddenOptDesc);

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

  try {
    po::variables_map optVm;
    po::store(po::command_line_parser(argc, argv).options(optDesc).positional(optPos).run(), optVm);
    po::notify(optVm);

    if (optVm.count("help") > 0) {
      usage(visibleOptDesc);
    }

    if (optVm.count("version") > 0) {
      std::cout << "ndnping " << tools::VERSION << std::endl;
      exit(0);
    }

    if (optVm.count("prefix") > 0) {
      options.prefix = Name(optVm["prefix"].as<std::string>());
    }
    else {
      std::cerr << "ERROR: No prefix specified" << std::endl;
      usage(visibleOptDesc);
    }

    options.interval = time::milliseconds(optVm["interval"].as<time::milliseconds::rep>());
    if (options.interval < getMinimumPingInterval()) {
      std::cerr << "ERROR: Specified ping interval is less than the minimum " <<
                   getMinimumPingInterval() << std::endl;
      usage(visibleOptDesc);
    }

    options.timeout = time::milliseconds(optVm["timeout"].as<time::milliseconds::rep>());

    if (optVm.count("count") > 0) {
      if (options.nPings <= 0) {
        std::cerr << "ERROR: Number of ping must be positive" << std::endl;
        usage(visibleOptDesc);
      }
    }

    if (optVm.count("start") > 0) {
      options.shouldGenerateRandomSeq = false;
    }

    if (optVm.count("identifier") > 0) {
      bool isIdentifierAcceptable = std::all_of(identifier.begin(), identifier.end(), &isalnum);
      if (identifier.empty() || !isIdentifierAcceptable) {
        std::cerr << "ERROR: Unacceptable client identifier" << std::endl;
        usage(visibleOptDesc);
      }

      options.clientIdentifier = name::Component(identifier);
    }

    if (optVm.count("cache") > 0) {
      options.shouldAllowStaleData = true;
    }

    if (optVm.count("timestamp") > 0) {
      options.shouldPrintTimestamp = true;
    }
  }
  catch (const po::error& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
    usage(visibleOptDesc);
  }

  std::cout << "PING " << options.prefix << std::endl;
  return Runner(options).run();
}

} // namespace client
} // namespace ping
} // namespace ndn

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