/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2018,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * 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>
 */

#include "core/version.hpp"

#include <ndn-cxx/security/signing-helpers.hpp>

#include <sstream>

namespace ndn {
namespace peek {

class NdnPoke : boost::noncopyable
{
public:
  explicit
  NdnPoke(const char* programName)
    : m_programName(programName)
    , m_wantForceData(false)
    , m_wantDigestSha256(false)
    , m_wantFinalBlockId(false)
    , m_freshnessPeriod(-1)
    , m_timeout(-1)
    , m_isDataSent(false)
  {
  }

  void
  usage()
  {
    std::cout << "\n Usage:\n " << m_programName << " "
      "[-f] [-D] [-i identity] [-F] [-x freshness] [-w timeout] ndn:/name\n"
      "   Reads payload from stdin and sends it to local NDN forwarder as a "
      "single Data packet\n"
      "   [-f]          - force, send Data without waiting for Interest\n"
      "   [-D]          - use DigestSha256 signing method instead of "
      "SignatureSha256WithRsa\n"
      "   [-i identity] - set identity to be used for signing\n"
      "   [-F]          - set FinalBlockId to the last component of Name\n"
      "   [-x]          - set FreshnessPeriod in time::milliseconds\n"
      "   [-w timeout]  - set Timeout in time::milliseconds\n"
      "   [-h]          - print help and exit\n"
      "   [-V]          - print version and exit\n"
      "\n";
    exit(1);
  }

  void
  setForceData()
  {
    m_wantForceData = true;
  }

  void
  setUseDigestSha256()
  {
    m_wantDigestSha256 = true;
  }

  void
  setIdentityName(const char* identityName)
  {
    m_identityName = make_shared<Name>(identityName);
  }

  void
  setLastAsFinalBlockId()
  {
    m_wantFinalBlockId = true;
  }

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

    m_freshnessPeriod = time::milliseconds(freshnessPeriod);
  }

  void
  setTimeout(int timeout)
  {
    if (timeout < 0)
      usage();

    m_timeout = time::milliseconds(timeout);
  }

  void
  setPrefixName(const char* prefixName)
  {
    m_prefixName = Name(prefixName);
  }

  time::milliseconds
  getDefaultTimeout()
  {
    return time::seconds(10);
  }

  shared_ptr<Data>
  createDataPacket()
  {
    auto dataPacket = make_shared<Data>(m_prefixName);

    std::stringstream payloadStream;
    payloadStream << std::cin.rdbuf();
    std::string payload = payloadStream.str();
    dataPacket->setContent(reinterpret_cast<const uint8_t*>(payload.c_str()), payload.length());

    if (m_freshnessPeriod >= time::milliseconds::zero())
      dataPacket->setFreshnessPeriod(m_freshnessPeriod);

    if (m_wantFinalBlockId) {
      if (!m_prefixName.empty())
        dataPacket->setFinalBlock(m_prefixName.get(-1));
      else {
        std::cerr << "Name Provided Has 0 Components" << std::endl;
        exit(1);
      }
    }

    if (m_wantDigestSha256) {
      m_keyChain.sign(*dataPacket, signingWithSha256());
    }
    else {
      if (m_identityName == nullptr) {
        m_keyChain.sign(*dataPacket);
      }
      else {
        m_keyChain.sign(*dataPacket, signingByIdentity(*m_identityName));
      }
    }

    return dataPacket;
  }

  void
  onInterest(const Name& name, const Interest& interest, const shared_ptr<Data>& data)
  {
    m_face.put(*data);
    m_isDataSent = true;
    m_face.shutdown();
  }

  void
  onRegisterFailed(const Name& prefix, const std::string& reason)
  {
    std::cerr << "Prefix Registration Failure." << std::endl;
    std::cerr << "Reason = " << reason << std::endl;
  }

  void
  run()
  {
    try {
      shared_ptr<Data> dataPacket = createDataPacket();
      if (m_wantForceData) {
        m_face.put(*dataPacket);
        m_isDataSent = true;
      }
      else {
        m_face.setInterestFilter(m_prefixName,
                                 bind(&NdnPoke::onInterest, this, _1, _2, dataPacket),
                                 RegisterPrefixSuccessCallback(),
                                 bind(&NdnPoke::onRegisterFailed, this, _1, _2));
      }

      if (m_timeout < time::milliseconds::zero())
        m_face.processEvents(getDefaultTimeout());
      else
        m_face.processEvents(m_timeout);
    }
    catch (const std::exception& e) {
      std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
      exit(1);
    }
  }

  bool
  isDataSent() const
  {
    return m_isDataSent;
  }

private:
  KeyChain m_keyChain;
  std::string m_programName;
  bool m_wantForceData;
  bool m_wantDigestSha256;
  shared_ptr<Name> m_identityName;
  bool m_wantFinalBlockId;
  time::milliseconds m_freshnessPeriod;
  time::milliseconds m_timeout;
  Name m_prefixName;
  bool m_isDataSent;
  Face m_face;
};

int
main(int argc, char* argv[])
{
  NdnPoke program(argv[0]);

  int option;
  while ((option = getopt(argc, argv, "hfDi:Fx:w:V")) != -1) {
    switch (option) {
    case 'h':
      program.usage();
      break;
    case 'f':
      program.setForceData();
      break;
    case 'D':
      program.setUseDigestSha256();
      break;
    case 'i':
      program.setIdentityName(optarg);
      break;
    case 'F':
      program.setLastAsFinalBlockId();
      break;
    case 'x':
      program.setFreshnessPeriod(atoi(optarg));
      break;
    case 'w':
      program.setTimeout(atoi(optarg));
      break;
    case 'V':
      std::cout << "ndnpoke " << tools::VERSION << std::endl;
      return 0;
    default:
      program.usage();
      break;
    }
  }

  argc -= optind;
  argv += optind;

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

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

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

} // namespace peek
} // namespace ndn

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