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