/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2014 Arizona Board of Regents
 *
 * This file is part of ndn-tlv-ping (Ping Application for Named Data Networking).
 *
 * ndn-tlv-ping is a 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-tlv-ping 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-tlv-ping, e.g., in LICENSE file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
 */

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/security/key-chain.hpp>

#include <boost/asio.hpp>
#include <boost/noncopyable.hpp>

namespace ndn {
namespace ping {

class NdnPingServer : boost::noncopyable
{
public:
  explicit
  NdnPingServer(char* programName)
    : m_programName(programName)
    , m_hasError(false)
    , m_isPrintTimestampSet(false)
    , m_freshnessPeriod(getMinimumFreshnessPeriod())
    , m_maximumPings(-1)
    , m_totalPings(0)
    , m_face(m_ioService)
  {
  }

  void
  usage()
  {
    std::cout << "\n Usage:\n " << m_programName << " ndn:/name/prefix [options]\n"
        " Starts a NDN ping server that responds to Interests with name"
        " ndn:/name/prefix/ping/number.\n"
        "   [-x freshness] - set FreshnessSeconds\n"
        "   [-p]           - specify number of pings to be satisfied (>=1)\n"
        "   [-t]           - print timestamp\n"
        "   [-h]           - print this message and exit\n\n";
    exit(1);
  }

  time::milliseconds
  getMinimumFreshnessPeriod()
  {
    return time::milliseconds(1000);
  }

  void
  setFreshnessPeriod(int freshnessPeriod)
  {
    if (freshnessPeriod <= 0)
      usage();

    m_freshnessPeriod = time::milliseconds(freshnessPeriod);
  }

  void
  setMaximumPings(int maximumPings)
  {
    if (maximumPings <= 0)
      usage();

    m_maximumPings = maximumPings;
  }

  void
  setPrefix(char* prefix)
  {
    m_prefix = prefix;
  }

  void
  setPrintTimestamp()
  {
    m_isPrintTimestampSet = true;
  }

  bool
  hasError() const
  {
    return m_hasError;
  }

  void
  onInterest(const Name& name, const Interest& interest)
  {
    Name interestName = interest.getName();

    if (m_isPrintTimestampSet)
      std::cout << time::toIsoString(time::system_clock::now())  << " - ";
    std::cout << "Interest Received - Ping Reference = "
              << interestName.at(-1).toUri() << std::endl;

    char responseContent[] = "NDN TLV Ping Response";
    shared_ptr<Data> data = make_shared<Data>(interestName);
    data->setFreshnessPeriod(m_freshnessPeriod);
    data->setContent(reinterpret_cast<const uint8_t*>(responseContent),
                     sizeof(responseContent));
    m_keyChain.sign(*data);
    m_face.put(*data);

    ++m_totalPings;
    if (m_maximumPings > 0 && m_maximumPings == m_totalPings) {
      std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
      std::cout << "Shutting Down Ping Server (" << m_name << ").\n" << std::endl;
      m_face.shutdown();
      m_ioService.stop();
    }
  }

  void
  onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
  {
    std::cerr << "ERROR: Failed to register prefix in local hub's daemon" << std::endl;
    std::cerr << "REASON: " << reason << std::endl;
    m_hasError = true;
    m_face.shutdown();
    m_ioService.stop();
  }

  void
  signalHandler()
  {
    std::cout << "\n\nTotal Ping Interests Processed = " << m_totalPings << std::endl;
    std::cout << "Shutting Down Ping Server (" << m_name.toUri() << ").\n" << std::endl;
    m_face.shutdown();
    exit(1);
  }

  void
  run()
  {
    std::cout << "\n=== Ping Server " << m_prefix <<" ===\n" << std::endl;

    boost::asio::signal_set signalSet(m_ioService, SIGINT, SIGTERM);
    signalSet.async_wait(bind([this]() { signalHandler(); }));

    m_name = m_prefix;
    m_name.append("ping");
    m_face.setInterestFilter(m_name,
                             bind(&NdnPingServer::onInterest,
                                  this, _1, _2),
                             bind(&NdnPingServer::onRegisterFailed,
                                  this, _1,_2));

    try {
      m_face.processEvents();
    }
    catch (std::exception& e) {
      std::cerr << "ERROR: " << e.what() << std::endl;
      m_hasError = true;
      m_ioService.stop();
    }
  }

private:
  char* m_programName;
  bool m_hasError;
  bool m_isPrintTimestampSet;
  time::milliseconds m_freshnessPeriod;
  int m_maximumPings;
  int m_totalPings;

  char* m_prefix;
  Name m_name;

  boost::asio::io_service m_ioService;
  KeyChain m_keyChain;
  Face m_face;
};

int
main(int argc, char* argv[])
{
  int res;

  NdnPingServer program(argv[0]);
  while ((res = getopt(argc, argv, "hdtp:x:")) != -1)
    {
      switch (res) {
      case 'h':
        program.usage();
        break;
      case 'p':
        program.setMaximumPings(atoi(optarg));
        break;
      case 'x':
        program.setFreshnessPeriod(atoi(optarg));
        break;
      case 't':
        program.setPrintTimestamp();
        break;
      default:
        program.usage();
        break;
      }
    }

  argc -= optind;
  argv += optind;

  if (argv[0] == 0)
    program.usage();

  program.setPrefix(argv[0]);
  program.run();

  std::cout << std::endl;

  if (program.hasError())
    return 1;
  else
    return 0;
}

} // namespace ping
} // namespace ndn

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