/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2013, Regents of the University of California
 * BSD license, See the LICENSE file for more information
 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
 */

#ifndef NDNSEC_CERT_GEN_HPP
#define NDNSEC_CERT_GEN_HPP

#include "ndnsec-util.hpp"

int 
ndnsec_cert_gen(int argc, char** argv)
{
  using boost::tokenizer;
  using boost::escaped_list_separator;

  using namespace ndn;
  namespace po = boost::program_options;

  std::string notBeforeStr;
  std::string notAfterStr;
  std::string sName;
  std::string reqFile;
  std::string signId;
  std::string subInfo;
  bool isSelfSigned = false;
  bool nack = false;

  po::options_description desc("General Usage\n  ndnsec cert-gen [-h] [-S date] [-E date] [-N subject-name] [-I subject-info] [-s sign-id] request\nGeneral options");
  desc.add_options()
    ("help,h", "produce help message")
    ("not-before,S", po::value<std::string>(&notBeforeStr), "certificate starting date, YYYYMMDDhhmmss")
    ("not-after,E", po::value<std::string>(&notAfterStr), "certificate ending date, YYYYMMDDhhmmss")
    ("subject-name,N", po::value<std::string>(&sName), "subject name")
    ("subject-info,I", po::value<std::string>(&subInfo), "subject info, pairs of OID and string description: \"2.5.4.10 'University of California, Los Angeles'\"")
    ("nack", "Generate revocation certificate (NACK)")
    ("sign-id,s", po::value<std::string>(&signId), "signing Identity, self-signed if not specified")
    ("request,r", po::value<std::string>(&reqFile), "request file name, - for stdin")
    ;

  po::positional_options_description p;
  p.add("request", 1);

  po::variables_map vm;
  try
    {
      po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
      po::notify(vm);
    }
  catch (std::exception &e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      return 1;
    }

  if (vm.count("help"))
    {
      std::cerr << desc << std::endl;
      return 0;
    }

  if (0 == vm.count("sign-id"))
    {     
      isSelfSigned = true;
    }

  if (vm.count("nack"))
    {
      nack = true;
    }

  std::vector<CertificateSubjectDescription> otherSubDescrypt;
  tokenizer<escaped_list_separator<char> > subInfoItems(subInfo, escaped_list_separator<char> ("\\", " \t", "'\""));

  tokenizer<escaped_list_separator<char> >::iterator it = subInfoItems.begin();
  try
    {
      while (it != subInfoItems.end())
        {
          std::string oid = *it;

          it++;
          if (it == subInfoItems.end ())
            {
              std::cerr << "ERROR: unmatched info for oid [" << oid << "]" << std::endl;
              return 1;
            }

          std::string value = *it;

          otherSubDescrypt.push_back (CertificateSubjectDescription(oid, value));

          it++;
        }
    }
  catch (std::exception &e)
    {
      std::cerr << "error in parsing subject info" << std::endl;
      return 1;
    }

  time::system_clock::TimePoint notBefore;
  time::system_clock::TimePoint notAfter;
  try{
    if (0 == vm.count("not-before"))
      {
        notBefore = time::system_clock::now();
      }
    else
      {
        notBefore = time::fromIsoString(notBeforeStr.substr(0, 8) + "T" + notBeforeStr.substr(8, 6));
      }


    if (0 == vm.count("not-after"))
      {
        notAfter = notBefore + time::days(365);
      }
    else
      {
        notAfter = time::fromIsoString(notAfterStr.substr(0, 8) + "T" + notAfterStr.substr(8, 6));
        if(notAfter < notBefore)
          {
            std::cerr << "not-before is later than not-after" << std::endl;
            return 1;
          }
      }
  }catch(std::exception & e){
    std::cerr << "Error in converting validity timestamp!" << std::endl;
    return 1;
  }

  if (0 == vm.count("request"))
    {
      std::cerr << "request file must be specified" << std::endl;
      return 1;
    }

  shared_ptr<IdentityCertificate> selfSignedCertificate = getIdentityCertificate(reqFile);
  if(!static_cast<bool>(selfSignedCertificate))
    {
      std::cerr << "ERROR: input error" << std::endl;
      return 1;
    }

  Name keyName = selfSignedCertificate->getPublicKeyName();
  Name signIdName;
  Name certName;

  if(isSelfSigned)
    {
      certName = keyName.getPrefix(keyName.size()-1);
      certName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
    }
  else
    {
      signIdName = Name(signId);
  
      Name::const_iterator i = keyName.begin();
      Name::const_iterator j = signIdName.begin();
      int count = 0;
      for(; i != keyName.end() && j != signIdName.end(); i++, j++, count++)
        {
          if(*i != *j)
            break;
        }
      
      if(j != signIdName.end() || i == keyName.end())
        {
          std::cerr << "wrong signing identity!" << std::endl;
          return 1;
        }

      certName = keyName.getSubName(0, count);
      certName.append("KEY").append(keyName.getSubName(count, keyName.size()-count));
      certName.append("ID-CERT").appendVersion ();
    }

  Block wire;

  if (!nack)
    {
      if (0 == vm.count("subject-name"))
        {
          std::cerr << "subject_name must be specified" << std::endl;
          return 1;
        }

      try
        {
          CertificateSubjectDescription subDescryptName("2.5.4.41", sName);
          IdentityCertificate certificate;
          certificate.setName(certName);
          certificate.setNotBefore(notBefore);
          certificate.setNotAfter(notAfter);
          certificate.setPublicKeyInfo(selfSignedCertificate->getPublicKeyInfo());
          certificate.addSubjectDescription(subDescryptName);
          for (size_t i = 0; i < otherSubDescrypt.size(); i++)
            certificate.addSubjectDescription(otherSubDescrypt[i]);
          certificate.encode();

          KeyChain keyChain;

          if(isSelfSigned)
            keyChain.selfSign(certificate);
          else
            {
              Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(Name(signId));
              
              keyChain.sign(certificate, signingCertificateName);
            }
          wire = certificate.wireEncode();
        }
      catch(SecPublicInfo::Error& e)
        {
          std::cerr << "ERROR: " << e.what() << std::endl;
          return 1;
        }
      catch(SecTpm::Error& e)
        {
          std::cerr << "ERROR: " << e.what() << std::endl;
          return 1;
        }
    }
  else
    {
      Data revocationCert;
      // revocationCert.setContent(void*, 0); // empty content
      revocationCert.setName(certName);

      try
        {
          KeyChain keyChain;
          
          Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(Name(signId));
          
          keyChain.sign (revocationCert, signingCertificateName);
          wire = revocationCert.wireEncode();
        }
      catch(SecPublicInfo::Error& e)
        {
          std::cerr << "ERROR: " << e.what() << std::endl;
          return 1;
        }
      catch(SecTpm::Error& e)
        {
          std::cerr << "ERROR: " << e.what() << std::endl;
          return 1;
        }
    }

  try
    {
      using namespace CryptoPP;
      StringSource ss(wire.wire(), wire.size(), true,
                      new Base64Encoder(new FileSink(std::cout), true, 64));
    }
  catch(CryptoPP::Exception& e)
    {
      std::cerr << "ERROR: " << e.what() << std::endl;
      return 1;
    }

  return 0;
}

#endif //NDNSEC_CERT_GEN_HPP
