/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "ndnsec.hpp"
#include "util.hpp"

namespace ndn {
namespace ndnsec {

int
ndnsec_dsk_gen(int argc, char** argv)
{
  using namespace ndn;
  using namespace ndn::security;
  namespace po = boost::program_options;

  std::string identityName;
  char keyType = 'r';

  po::options_description description("General Usage\n"
                                      "  ndnsec dsk-gen [-h] [-t keyType] identity\n"
                                      "General options");
  description.add_options()
    ("help,h", "produce help message")
    ("identity,i", po::value<std::string>(&identityName),
     "identity name, for example, /ndn/ucla.edu/alice")
    ("type,t", po::value<char>(&keyType)->default_value('r'),
     "optional, key type, r for RSA key (default), e for EC key.")
    // ("size,s", po::value<int>(&keySize)->default_value(2048),
    //  "optional, key size, 2048 (default)")
    ;

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

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

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

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

  shared_ptr<security::v1::IdentityCertificate> kskCert;
  Name signingCertName;

  security::v1::KeyChain keyChain;

  try {
    Name defaultCertName = keyChain.getDefaultCertificateNameForIdentity(identityName);
    bool isDefaultDsk = false;
    std::string keyUsageTag = defaultCertName.get(-3).toUri().substr(0, 4);
    if (keyUsageTag == "ksk-")
      isDefaultDsk = false;
    else if (keyUsageTag == "dsk-")
      isDefaultDsk = true;
    else {
      std::cerr << "ERROR: Unknown key usage tag: " << keyUsageTag << std::endl;
      return 1;
    }

    if (isDefaultDsk) {
      shared_ptr<security::v1::IdentityCertificate> dskCert = keyChain.getCertificate(defaultCertName);

      if (dskCert != nullptr) {
        SignatureSha256WithRsa sha256sig(dskCert->getSignature());

        Name keyLocatorName = sha256sig.getKeyLocator().getName();

        Name kskName = security::v1::IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
        Name kskCertName = keyChain.getDefaultCertificateNameForKey(kskName);
        signingCertName = kskCertName;
        kskCert = keyChain.getCertificate(kskCertName);
      }
      else {
        std::cerr << "ERROR: The default certificate is missing." << std::endl;
        return 1;
      }
    }
    else {
      signingCertName = defaultCertName;
      kskCert = keyChain.getCertificate(defaultCertName);
    }

    if (kskCert == nullptr) {
      std::cerr << "ERROR: KSK certificate is missing." << std::endl;
      return 1;
    }

    Name newKeyName;
    switch (keyType) {
      case 'r': {
        RsaKeyParams params;
        newKeyName = keyChain.generateRsaKeyPair(Name(identityName), false, params.getKeySize());
        if (0 == newKeyName.size()) {
          std::cerr << "ERROR: Fail to generate RSA key!" << std::endl;
          return 1;
        }
        break;
      }
      case 'e': {
        EcKeyParams params;
        newKeyName = keyChain.generateEcKeyPair(Name(identityName), false, params.getKeySize());
        if (0 == newKeyName.size()) {
          std::cerr << "ERROR: Fail to generate EC key!" << std::endl;
          return 1;
        }
        break;
      }
      default:
        std::cerr << "ERROR: Unrecongized key type"
                  << "\n";
        std::cerr << description << std::endl;
        return 1;
    }

    Name certName = newKeyName.getPrefix(-1);
    certName.append("KEY").append(newKeyName.get(-1)).append("ID-CERT").appendVersion();

    shared_ptr<security::v1::IdentityCertificate> certificate =
      keyChain.prepareUnsignedIdentityCertificate(newKeyName,
                                                  Name(identityName),
                                                  kskCert->getNotBefore(),
                                                  kskCert->getNotAfter(),
                                                  kskCert->getSubjectDescriptionList());

    if (certificate != nullptr)
      certificate->encode();
    else {
      std::cerr << "ERROR: Cannot format the certificate of the requested dsk."
                << "\n";
      return 1;
    }

    keyChain.sign(*certificate,
                  security::SigningInfo(security::SigningInfo::SIGNER_TYPE_CERT, signingCertName));

    keyChain.addCertificateAsIdentityDefault(*certificate);

    std::cerr << "OK: dsk certificate with name [" << certificate->getName()
              << "] has been successfully installed\n";
    return 0;
  }
  catch (const std::runtime_error& e) {
    std::cerr << "ERROR: other runtime errors: " << e.what() << "\n";
    return 1;
  }
}

} // namespace ndnsec
} // namespace ndn
