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

#include "challenge-module.hpp"
#include "logging.hpp"
#include <ndn-cxx/util/random.hpp>

namespace ndn {
namespace ndncert {

_LOG_INIT(ndncert.challenge-module);

const std::string ChallengeModule::WAIT_SELECTION = "wait-selection";
const std::string ChallengeModule::SUCCESS = "success";
const std::string ChallengeModule::PENDING = "pending";
const std::string ChallengeModule::FAILURE = "failure";

ChallengeModule::ChallengeModule(const std::string& uniqueType)
  : CHALLENGE_TYPE(uniqueType)
{
}

ChallengeModule::~ChallengeModule() = default;

unique_ptr<ChallengeModule>
ChallengeModule::createChallengeModule(const std::string& canonicalName)
{
  ChallengeFactory& factory = getFactory();
  auto i = factory.find(canonicalName);
  return i == factory.end() ? nullptr : i->second();
}

JsonSection
ChallengeModule::handleChallengeRequest(const Interest& interest, CertificateRequest& request)
{
  int pos = request.getCaName().size() + 1;
  const Name& interestName = interest.getName();
  std::string interestType = interestName.get(pos).toUri();

  _LOG_TRACE("Incoming challenge request. type: " << interestType);

  if (interestType == "_SELECT") {
    return processSelectInterest(interest, request);
  }
  else if (interestType == "_VALIDATE"){
    return processValidateInterest(interest, request);
  }
  else {
    return processStatusInterest(interest, request);
  }
}

std::list<std::string>
ChallengeModule::getRequirementForSelect()
{
  return getSelectRequirements();
}

std::list<std::string>
ChallengeModule::getRequirementForValidate(const std::string& status)
{
  return getValidateRequirements(status);
}

JsonSection
ChallengeModule::genSelectParamsJson(const std::string& status,
                                     const std::list<std::string>& paramList)
{
  return doGenSelectParamsJson(status, paramList);
}

JsonSection
ChallengeModule::genValidateParamsJson(const std::string& status,
                                     const std::list<std::string>& paramList)
{
  return doGenValidateParamsJson(status, paramList);
}

JsonSection
ChallengeModule::processStatusInterest(const Interest& interest, const CertificateRequest& request)
{
  // interest format: /CA/_STATUS/{"request-id":"id"}/<signature>
  if (request.getStatus() == SUCCESS) {
    Name downloadName = genDownloadName(request.getCaName(), request.getStatus());
    return genResponseChallengeJson(request.getRequestId(), request.getChallengeType(),
                                    SUCCESS, downloadName);
  }
  else
    return genResponseChallengeJson(request.getRequestId(), request.getChallengeType(),
                                    request.getStatus());
}

JsonSection
ChallengeModule::getJsonFromNameComponent(const Name& name, int pos)
{
  std::string jsonString = encoding::readString(name.get(pos));
  std::istringstream ss(jsonString);
  JsonSection json;
  boost::property_tree::json_parser::read_json(ss, json);
  return json;
}

Name
ChallengeModule::genDownloadName(const Name& caName, const std::string& requestId)
{
  JsonSection json;
  json.put(JSON_REQUEST_ID, requestId);
  std::stringstream ss;
  boost::property_tree::write_json(ss, json);
  Block jsonBlock = makeStringBlock(ndn::tlv::NameComponent, ss.str());
  Name name = caName;
  name.append("_DOWNLOAD").append(jsonBlock);
  return name;
}

ChallengeModule::ChallengeFactory&
ChallengeModule::getFactory()
{
  static ChallengeModule::ChallengeFactory factory;
  return factory;
}

std::string
ChallengeModule::generateSecretCode()
{
  uint32_t securityCode = 0;
  do {
    securityCode = random::generateSecureWord32();
  }
  while (securityCode >= 4294000000);
  securityCode /= 4294;
  std::string result = std::to_string(securityCode);
  while (result.length() < 6) {
    result = "0" + result;
  }
  return result;
}

} // namespace ndncert
} // namespace ndn
