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

class HttpException : public std::runtime_error
{
public:
  explicit
  HttpException(const std::string& what)
    : std::runtime_error(what)
  {
  }
};

security::v2::Certificate
getCertificateHttp(const std::string& host, const std::string& port, const std::string& path)
{
  using namespace boost::asio::ip;
  tcp::iostream requestStream;

  requestStream.expires_from_now(boost::posix_time::milliseconds(3000));

  requestStream.connect(host, port);
  if (!requestStream) {
    BOOST_THROW_EXCEPTION(HttpException("HTTP connection error"));
  }
  requestStream << "GET " << path << " HTTP/1.0\r\n";
  requestStream << "Host: " << host << "\r\n";
  requestStream << "Accept: */*\r\n";
  requestStream << "Cache-Control: no-cache\r\n";
  requestStream << "Connection: close\r\n\r\n";
  requestStream.flush();

  std::string statusLine;
  std::getline(requestStream, statusLine);
  if (!requestStream) {
    BOOST_THROW_EXCEPTION(HttpException("HTTP communication error"));
  }

  std::stringstream responseStream(statusLine);
  std::string httpVersion;
  responseStream >> httpVersion;
  unsigned int statusCode;
  responseStream >> statusCode;
  std::string statusMessage;

  std::getline(responseStream, statusMessage);
  if (!requestStream || httpVersion.substr(0, 5) != "HTTP/") {
    BOOST_THROW_EXCEPTION(HttpException("HTTP communication error"));
  }
  if (statusCode != 200) {
    BOOST_THROW_EXCEPTION(HttpException("HTTP server error"));
  }
  std::string header;
  while (std::getline(requestStream, header) && header != "\r")
    ;

  ndn::OBufferStream os;
  {
    using namespace ndn::security::transform;
    streamSource(requestStream) >> base64Decode(true) >> streamSink(os);
  }

  return security::v2::Certificate(Block(os.buf()));
}

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

  std::string certFileName;
  bool isSystemDefault = true;
  bool isIdentityDefault = false;
  bool isKeyDefault = false;

  po::options_description description("General Usage\n  ndnsec cert-install [-h] [-I|K|N] cert-file\nGeneral options");
  description.add_options()
    ("help,h", "produce help message")
    ("cert-file,f", po::value<std::string>(&certFileName), "file name of the ceritificate, - for stdin. "
                                                      "If starts with http://, will try to fetch "
                                                      "the certificate using HTTP GET request")
    ("identity-default,I", "optional, if specified, the certificate will be set as the default certificate of the identity")
    ("key-default,K", "optional, if specified, the certificate will be set as the default certificate of the key")
    ("no-default,N", "optional, if specified, the certificate will be simply installed")
    ;
  po::positional_options_description p;
  p.add("cert-file", 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;
    return 1;
  }

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

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

  if (vm.count("identity-default") != 0) {
    isIdentityDefault = true;
    isSystemDefault = false;
  }
  else if (vm.count("key-default") != 0) {
    isKeyDefault = true;
    isSystemDefault = false;
  }
  else if (vm.count("no-default") != 0) {
    // noDefault = true;
    isSystemDefault = false;
  }

  security::v2::Certificate cert;

  try {
  if (certFileName.find("http://") == 0) {
    std::string host;
    std::string port;
    std::string path;

    size_t pos = 7; // offset of "http://"
    size_t posSlash = certFileName.find("/", pos);

    if (posSlash == std::string::npos)
      BOOST_THROW_EXCEPTION(HttpException("Request line is not correctly formatted"));

    size_t posPort = certFileName.find(":", pos);

    if (posPort != std::string::npos && posPort < posSlash) {
      // port is specified
      port = certFileName.substr(posPort + 1, posSlash - posPort - 1);
      host = certFileName.substr(pos, posPort - pos);
    }
    else {
      port = "80";
      host = certFileName.substr(pos, posSlash - pos);
    }

    path = certFileName.substr(posSlash, certFileName.size() - posSlash);

    cert = getCertificateHttp(host, port, path);
  }
  else {
    cert = loadCertificate(certFileName);
  }
  }
  catch (const CannotLoadCertificate&) {
    std::cerr << "ERROR: Cannot load the certificate " << certFileName << std::endl;
    return 1;
  }

  security::v2::KeyChain keyChain;
  security::Identity id;
  security::Key key;
  try {
    id = keyChain.getPib().getIdentity(cert.getIdentity());
    key = id.getKey(cert.getKeyName());
  }
  catch (const security::Pib::Error& e) {
    std::cerr << "ERROR: " << e.what() << std::endl;
  }

  keyChain.addCertificate(key, cert);

  if (isSystemDefault) {
    keyChain.setDefaultIdentity(id);
    keyChain.setDefaultKey(id, key);
    keyChain.setDefaultCertificate(key, cert);
  }
  else if (isIdentityDefault) {
    keyChain.setDefaultKey(id, key);
    keyChain.setDefaultCertificate(key, cert);
  }
  else if (isKeyDefault) {
    keyChain.setDefaultCertificate(key, cert);
  }

  std::cerr << "OK: certificate with name [" << cert.getName().toUri() << "] "
            << "has been successfully installed" << std::endl;

  return 0;
}

} // namespace ndnsec
} // namespace ndn
