/* -*- 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 {

void
printCertificate(security::v1::KeyChain& keyChain,
                 const ndn::Name& certName,
                 bool isDefault,
                 int verboseLevel)
{
  if (isDefault)
    std::cout << "       +->* ";
  else
    std::cout << "       +->  ";

  std::cout << certName << std::endl;

  if (verboseLevel >= 3) {
    shared_ptr<security::v1::IdentityCertificate> certificate = keyChain.getCertificate(certName);
    if (certificate != nullptr)
      certificate->printCertificate(std::cout, "            ");
  }
}

void
printKey(security::v1::KeyChain& keyChain, const ndn::Name& keyName, bool isDefault, int verboseLevel)
{
  if (isDefault)
    std::cout << "  +->* ";
  else
    std::cout << "  +->  ";

  std::cout << keyName << std::endl;

  if (verboseLevel >= 2) {
    std::vector<ndn::Name> defaultCertificates;
    keyChain.getAllCertificateNamesOfKey(keyName, defaultCertificates, true);

    for (const auto& certName : defaultCertificates)
      printCertificate(keyChain, certName, true, verboseLevel);

    std::vector<ndn::Name> otherCertificates;
    keyChain.getAllCertificateNamesOfKey(keyName, otherCertificates, false);
    for (const auto& certName : otherCertificates)
      printCertificate(keyChain, certName, false, verboseLevel);
  }
}

void
printIdentity(security::v1::KeyChain& keyChain,
              const ndn::Name& identity,
              bool isDefault,
              int verboseLevel)
{
  if (isDefault)
    std::cout << "* ";
  else
    std::cout << "  ";

  std::cout << identity << std::endl;

  if (verboseLevel >= 1) {
    std::vector<ndn::Name> defaultKeys;
    keyChain.getAllKeyNamesOfIdentity(identity, defaultKeys, true);
    for (const auto& keyName : defaultKeys)
      printKey(keyChain, keyName, true, verboseLevel);

    std::vector<ndn::Name> otherKeys;
    keyChain.getAllKeyNamesOfIdentity(identity, otherKeys, false);
    for (const auto& keyName : otherKeys) {
      printKey(keyChain, keyName, false, verboseLevel);
    }

    std::cout << std::endl;
  }
}

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

  int verboseLevel = 0; // 0 print identity only
                        // 1 print key name
                        // 2 print cert name
                        // 3 print cert content

  po::options_description options("General Usage\n  ndnsec list [-h] [-k|c]\nGeneral options");
  options.add_options()
    ("help,h",    "produce help message")
    ("key,k",     "granularity: key")
    ("cert,c",    "granularity: certificate")
    ("verbose,v", accumulator<int>(&verboseLevel),
                  "verbose mode: -v is equivalent to -k, -vv is equivalent to -c")
    ;

  po::options_description oldOptions;
  oldOptions.add_options()
    ("key2,K",         "granularity: key")
    ("cert2,C",        "granularity: certificate");

  po::options_description allOptions;
  allOptions.add(options).add(oldOptions);

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

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

  int tmpVerboseLevel = 0;
  if (vm.count("cert") != 0 || vm.count("cert2") != 0)
    tmpVerboseLevel = 2;
  else if (vm.count("key") != 0 || vm.count("key2") != 0)
    tmpVerboseLevel = 1;

  verboseLevel = std::max(verboseLevel, tmpVerboseLevel);

  security::v1::KeyChain keyChain;

  std::vector<Name> defaultIdentities;
  keyChain.getAllIdentities(defaultIdentities, true);
  for (const auto& identity : defaultIdentities) {
    printIdentity(keyChain, identity, true, verboseLevel);
  }

  std::vector<Name> otherIdentities;
  keyChain.getAllIdentities(otherIdentities, false);
  for (const auto& identity : otherIdentities) {
    printIdentity(keyChain, identity, false, verboseLevel);
  }

  return 0;
}

} // namespace ndnsec
} // namespace ndn
