/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2017, 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.
 */

#ifndef NDNCERT_CHALLENGE_MODULE_HPP
#define NDNCERT_CHALLENGE_MODULE_HPP

#include "ndncert-common.hpp"
#include "certificate-request.hpp"
#include "json-helper.hpp"

namespace ndn {
namespace ndncert {

class ChallengeModule : noncopyable
{
public:
  /**
   * @brief Error that can be thrown from ChallengeModule
   *
   * ChallengeModule should throw Error to notice CA there's an Error. In this case, CA will
   * generate an Error JSON file back to end entity.
   */
  class Error : public std::runtime_error
  {
  public:
    using std::runtime_error::runtime_error;
  };

public:
  ChallengeModule(const std::string& uniqueType);

  template<class ChallengeType>
  static void
  registerChallengeModule(const std::string& typeName)
  {
    ChallengeFactory& factory = getFactory();
    BOOST_ASSERT(factory.count(typeName) == 0);
    factory[typeName] = [] { return make_unique<ChallengeType>(); };
  }

  static unique_ptr<ChallengeModule>
  createChallengeModule(const std::string& ChallengeType);

  /**
   * @brief Handle the challenge related interest and update certificate request.
   * @note Should be used by CA Module
   * @note Signature of interest should already be validated by CA Module
   *
   * When CA receives a SELECT or a VALIDATE or a STATUS interest, CA should invoke the function
   * to enable selected challenge to go on the verification process.
   *
   * @param interest The request interest packet
   * @param request The CertificateRequest instance
   * @return the JSON file as the response data content
   */
  JsonSection
  handleChallengeRequest(const Interest& interest, CertificateRequest& request);

  /**
   * @brief Get requirements for requester before sending SELECT interest.
   * @note Should be used by Client Module
   *
   * Before requester sends a USE interest, client should invoke the function to
   * get input instruction and expose the instruction to requester.
   *
   * Every item in the return list requires a input from requester. The item itself is
   * an instruction for requester.
   *
   * @return the input instruction for requester
   */
  std::list<std::string>
  getRequirementForSelect();

  /**
   * @brief Get requirements for requester before sending VALIDATE interest.
   * @note Should be used by Client Module
   *
   * Before requester sends a POLL interest, client should invoke the function to
   * get input instruction and expose the instruction to requester.
   *
   * Every item in the return list requires a input from requester. The item itself is
   * an instruction for requester.
   *
   * @param status of the challenge
   * @return the input instruction for requester
   */
  std::list<std::string>
  getRequirementForValidate(const std::string& status);

  /**
   * @brief Generate ChallengeInfo part for SELECT and VALIDATE interest.
   * @note Should be used by Client Module
   *
   * After requester provides required information, client should invoke the function to
   * generate the ChallengeInfo part of the interest.
   *
   * @param interestType of the request
   * @param status of the challenge
   * @param paramList contains all the input from requester
   * @return the JSON file of ChallengeInfo
   */
  JsonSection
  genRequestChallengeInfo(const std::string& interestType, const std::string& status,
                          const std::list<std::string>& paramList);

PUBLIC_WITH_TESTS_ELSE_PROTECTED:
  virtual JsonSection
  processSelectInterest(const Interest& interest, CertificateRequest& request) = 0;

  virtual JsonSection
  processValidateInterest(const Interest& interest, CertificateRequest& request) = 0;

  virtual std::list<std::string>
  getSelectRequirements() = 0;

  virtual std::list<std::string>
  getValidateRequirements(const std::string& status) = 0;

  virtual JsonSection
  genChallengeInfo(const std::string& interestType, const std::string& status,
                   const std::list<std::string>& paramList) = 0;

  virtual JsonSection
  processStatusInterest(const Interest& interest, const CertificateRequest& request);

  static JsonSection
  getJsonFromNameComponent(const Name& name, int pos);

  static Name
  genDownloadName(const Name& caName, const std::string& requestId);

  static std::string
  generateSecretCode();

public:
  const std::string CHALLENGE_TYPE;
  static const std::string WAIT_SELECTION;
  static const std::string SUCCESS;
  static const std::string PENDING;

private:
  typedef function<unique_ptr<ChallengeModule> ()> ChallengeCreateFunc;
  typedef std::map<std::string, ChallengeCreateFunc> ChallengeFactory;

  static ChallengeFactory&
  getFactory();
};

#define NDNCERT_REGISTER_CHALLENGE(C, T)                           \
static class NdnCert ## C ## ChallengeRegistrationClass            \
{                                                                  \
public:                                                            \
  NdnCert ## C ## ChallengeRegistrationClass()                     \
  {                                                                \
    ::ndn::ndncert::ChallengeModule::registerChallengeModule<C>(T);\
  }                                                                \
} g_NdnCert ## C ## ChallengeRegistrationVariable

} // namespace ndncert
} // namespace ndn

#endif // NDNCERT_CHALLENGE_MODULE_HPP
