/* -*- 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.
 *
 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
 */

#ifndef NDN_TOOLS_NDNSEC_LIST_HPP
#define NDN_TOOLS_NDNSEC_LIST_HPP

#include "util.hpp"

void
printCertificate(ndn::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) {
    ndn::shared_ptr<ndn::security::v1::IdentityCertificate> certificate = keyChain.getCertificate(certName);
    if (static_cast<bool>(certificate))
      certificate->printCertificate(std::cout, "            ");
  }
}

void
printKey(ndn::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(ndn::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);

  ndn::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;
}

#endif // NDN_TOOLS_NDNSEC_LIST_HPP
