/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  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 NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
 */

#include "version.hpp"

#include <boost/utility.hpp>

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

namespace ndntlvpoke {

class NdnTlvPoke : boost::noncopyable
{

public:

  explicit
  NdnTlvPoke(char* programName)
    : m_programName(programName)
    , m_isForceDataSet(false)
    , m_isUseDigestSha256Set(false)
    , m_isLastAsFinalBlockIdSet(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_isForceDataSet = true;
  }

  void
  setUseDigestSha256()
  {
    m_isUseDigestSha256Set = true;
  }

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

  void
  setLastAsFinalBlockId()
  {
    m_isLastAsFinalBlockIdSet = true;
  }

  void
  setFreshnessPeriod(int freshnessPeriod)
  {
    if (freshnessPeriod < 0)
      usage();
    m_freshnessPeriod = ndn::time::milliseconds(freshnessPeriod);
  }

  void
  setTimeout(int timeout)
  {
    if (timeout < 0)
      usage();
    m_timeout = ndn::time::milliseconds(timeout);
  }

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

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

  ndn::Data
  createDataPacket()
  {
    ndn::Data dataPacket(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 >= ndn::time::milliseconds::zero())
      dataPacket.setFreshnessPeriod(m_freshnessPeriod);
    if (m_isLastAsFinalBlockIdSet)
      {
        if (!m_prefixName.empty())
          dataPacket.setFinalBlockId(m_prefixName.get(-1));
        else
          {
            std::cerr << "Name Provided Has 0 Components" << std::endl;
            exit(1);
          }
      }
    if (m_isUseDigestSha256Set)
      m_keyChain.signWithSha256(dataPacket);
    else
      {
        if (!static_cast<bool>(m_identityName))
          m_keyChain.sign(dataPacket);
        else
          m_keyChain.signByIdentity(dataPacket, *m_identityName);
      }
    return dataPacket;
  }

  void
  onInterest(const ndn::Name& name,
             const ndn::Interest& interest,
             const ndn::Data& dataPacket)
  {
    m_face.put(dataPacket);
    m_isDataSent = true;
    m_face.shutdown();
  }

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

  void
  run()
  {
    try
      {
        ndn::Data dataPacket = createDataPacket();
        if (m_isForceDataSet)
          {
            m_face.put(dataPacket);
            m_isDataSent = true;
          }
        else
          {
            m_face.setInterestFilter(m_prefixName,
                                     ndn::bind(&NdnTlvPoke::onInterest,
                                               this, _1, _2, dataPacket),
                                     ndn::RegisterPrefixSuccessCallback(),
                                     ndn::bind(&NdnTlvPoke::onRegisterFailed,
                                               this, _1, _2));
          }
        if (m_timeout < ndn::time::milliseconds::zero())
          m_face.processEvents(getDefaultTimeout());
        else
          m_face.processEvents(m_timeout);
      }
    catch (std::exception& e)
      {
        std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
        exit(1);
      }
  }

  bool
  isDataSent() const
  {
    return m_isDataSent;
  }

private:

  ndn::KeyChain m_keyChain;
  std::string m_programName;
  bool m_isForceDataSet;
  bool m_isUseDigestSha256Set;
  ndn::shared_ptr<ndn::Name> m_identityName;
  bool m_isLastAsFinalBlockIdSet;
  ndn::time::milliseconds m_freshnessPeriod;
  ndn::time::milliseconds m_timeout;
  ndn::Name m_prefixName;
  bool m_isDataSent;
  ndn::Face m_face;

};

}

int
main(int argc, char* argv[])
{
  int option;
  ndntlvpoke::NdnTlvPoke ndnTlvPoke(argv[0]);
  while ((option = getopt(argc, argv, "hfDi:Fx:w:V")) != -1) {
    switch (option) {
    case 'h':
      ndnTlvPoke.usage();
      break;
    case 'f':
      ndnTlvPoke.setForceData();
      break;
    case 'D':
      ndnTlvPoke.setUseDigestSha256();
      break;
    case 'i':
      ndnTlvPoke.setIdentityName(optarg);
      break;
    case 'F':
      ndnTlvPoke.setLastAsFinalBlockId();
      break;
    case 'x':
      ndnTlvPoke.setFreshnessPeriod(atoi(optarg));
      break;
    case 'w':
      ndnTlvPoke.setTimeout(atoi(optarg));
      break;
    case 'V':
      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
      return 0;
    default:
      ndnTlvPoke.usage();
      break;
    }
  }

  argc -= optind;
  argv += optind;

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

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

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