/* -*- 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 "core/version.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:V")) != -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;
      case 'V':
        std::cout << "ndnpingserver " << tools::VERSION << std::endl;
        return 0;
     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);
}
