/**
 * This program is used by test_nack interation test.
 * The program implements a simple consumer that sends one or
 * two interests and prints the network response (timeout, data or nack).
 * ndnpeek is not sufficient since it does not allow verifying
 * the nonces as required by the test.
 */

#include <boost/asio.hpp>
#include <ndn-cxx/face.hpp>

#include <iostream>

namespace ndn {

class TestNackConsumer : boost::noncopyable
{
public:
  explicit
  TestNackConsumer(const char* programName)
    : m_programName(programName)
    , m_face(m_ioService)
    , m_interestLifetime(time::milliseconds(4000))
    , m_secondInterestInterval(time::milliseconds(0))
  {
    m_nonce1 = static_cast<uint32_t>(std::rand());
    m_nonce2 = static_cast<uint32_t>(std::rand());
  }

  void
  usage() const
  {
    std::cout << "Usage:\n"
              << "  " << m_programName
              << "  -p <name> -w <wait_before_quit> [-r second_Interest_interval] \n"
              << "\n"
              << "  -p <name> Interest prefix\n"
              << "  -w <wait_before_quit> - wait time(ms) before exit\n"
              << "\n"
              << "Options:\n"
              << "  [-r second_Interest_interval] - set the time (ms) between first and second Interests\n"
              << "  [-h]          - print this help text and exit\n";
    exit(EXIT_FAILURE);
  }

  void setInterestName(const Name& prefix)
  {
    m_interestName = prefix;
  }

  void
  setSecondInterestInterval(int interestInterval)
  {
    if (interestInterval <= 0)
      usage();
    m_secondInterestInterval = time::milliseconds(interestInterval);
  }

  void
  setWaitBeforeQuit(int waitTime)
  {
    if (waitTime <= 0)
      usage();
    m_waitBeforeQuit = time::milliseconds(waitTime);
  }

  void
  signalHandler()
  {
    m_face.shutdown();
    m_ioService.stop();

    exit(EXIT_FAILURE);
  }

  void
  onData(const Interest& interest, const Data& data)
  {
    std::cout << "DATA received for: " << interest.getName() << std::endl;
  }

  void
  onTimeout(const Interest& interest)
  {
    std::cout << "TIMEOUT received for: " << interest.getName() << std::endl;
  }

  void
  onNack(const Interest& interest,
         const lp::Nack& nack)
  {
    std::cout << "NACK received for: " << interest.getName()
              << " Nonce: " << interest.getNonce()
              << " Reason: " << nack.getReason()
              << std::endl;
  }
  void
  sendSecondInterest(boost::asio::deadline_timer* timer)
  {
    Interest interest(m_interestName);
    interest.setInterestLifetime(m_interestLifetime);
    interest.setNonce(m_nonce2);

    std::cout << "Sending Interest 2: " << interest.getName()
              << " Nonce: " << interest.getNonce()
              << std::endl;

    m_face.expressInterest(interest,
                           bind(&TestNackConsumer::onData,
                                this, _1, _2),
                           bind(&TestNackConsumer::onNack,
                                this, _1, _2),
                           bind(&TestNackConsumer::onTimeout,
                                this, _1));
  }

  void
  exitProgram(boost::asio::deadline_timer* timer)
  {
    m_face.shutdown();
    m_ioService.stop();
  }

  void
  run()
  {
    boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
    signalSet.async_wait(bind(&TestNackConsumer::signalHandler, this));

    boost::asio::deadline_timer sendSecondInterestTimer(m_ioService,
                                                        boost::posix_time::millisec(m_secondInterestInterval.count()));
    boost::asio::deadline_timer exitTimer(m_ioService,
                                          boost::posix_time::millisec(m_waitBeforeQuit.count()));

    sendSecondInterestTimer.expires_at(sendSecondInterestTimer.expires_at() +
                      boost::posix_time::millisec(m_secondInterestInterval.count()));
    exitTimer.expires_at(exitTimer.expires_at() +
                      boost::posix_time::millisec(m_waitBeforeQuit.count()));

    try {
      Interest interest(m_interestName);
      interest.setInterestLifetime(m_interestLifetime);
      interest.setNonce(m_nonce1);

      std::cout << "Sending Interest 1: " << interest.getName()
                << " Nonce: " << interest.getNonce()
                << std::endl;

      m_face.expressInterest(interest,
                             bind(&TestNackConsumer::onData,
                                  this, _1, _2),
                             bind(&TestNackConsumer::onNack,
                                  this, _1, _2),
                             bind(&TestNackConsumer::onTimeout,
                                  this, _1));

      if (m_secondInterestInterval != time::milliseconds(0))
      {
        // Schedule second interest
        sendSecondInterestTimer.async_wait(bind(&TestNackConsumer::sendSecondInterest,
                                                this,
                                                &sendSecondInterestTimer));
      }

      // Schedule exit
      exitTimer.async_wait(bind(&TestNackConsumer::exitProgram, this, &exitTimer));
      m_face.processEvents();
    }
    catch (const std::exception& exception) {
      m_ioService.stop();
    }
  }

private:
  boost::asio::io_service m_ioService;
  std::string m_programName;
  Face m_face;
  Name m_interestName;
  time::milliseconds m_interestLifetime;
  time::milliseconds m_secondInterestInterval;
  time::milliseconds m_waitBeforeQuit;
  uint32_t  m_nonce1;
  uint32_t  m_nonce2;
};

} // namespace ndn

int
main(int argc, char* argv[])
{
  std::srand(std::time(nullptr));
  int argNumber = 0;
  ndn::TestNackConsumer testNackConsumer(argv[0]);

  int option;
  while ((option = getopt(argc, argv, "hp:r:w:")) != -1) {
    switch (option) {
      case 'h':
        testNackConsumer.usage();
        break;
      case 'p':
        testNackConsumer.setInterestName(ndn::Name(optarg));
        ++argNumber;
        break;
      case 'r':
        testNackConsumer.setSecondInterestInterval(atoi(optarg));
        break;
      case 'w':
        testNackConsumer.setWaitBeforeQuit(atoi(optarg));
        ++argNumber;
        break;
      default:
        testNackConsumer.usage();
        break;
    }
  }

  argc -= optind;
  argv += optind;

  if (argc || argNumber < 2)
    testNackConsumer.usage();

  testNackConsumer.run();

  return 0;
}
