/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2017-2019, 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-pin.hpp"
#include <ndn-cxx/util/random.hpp>

namespace ndn {
namespace ndncert {

_LOG_INIT(ndncert.challenge.pin);
NDNCERT_REGISTER_CHALLENGE(ChallengePin, "pin");

const std::string ChallengePin::NEED_CODE = "need-code";
const std::string ChallengePin::WRONG_CODE = "wrong-code";
const std::string ChallengePin::PARAMETER_KEY_CODE = "pin-code";

ChallengePin::ChallengePin(const size_t& maxAttemptTimes, const time::seconds& secretLifetime)
    : ChallengeModule("pin")
    , m_secretLifetime(secretLifetime)
    , m_maxAttemptTimes(maxAttemptTimes)
{
}

// For CA
std::tuple<ErrorCode, std::string>
ChallengePin::handleChallengeRequest(const Block& params, CertificateRequest& request)
{
  params.parse();
  auto currentTime = time::system_clock::now();
  if (request.m_status == Status::BEFORE_CHALLENGE) {
    _LOG_TRACE("Challenge Interest arrives. Init the challenge");
    // for the first time, init the challenge
    std::string secretCode = generateSecretCode();
    JsonSection secretJson;
    secretJson.add(PARAMETER_KEY_CODE, secretCode);
    _LOG_TRACE("Secret for request " << request.m_requestId << " : " << secretCode);
    return returnWithNewChallengeStatus(request, NEED_CODE, std::move(secretJson), m_maxAttemptTimes, m_secretLifetime.count());
  }

  if (request.m_challengeStatus == NEED_CODE || request.m_challengeStatus == WRONG_CODE) {
    _LOG_TRACE("Challenge Interest arrives. Challenge Status: " << request.m_challengeStatus);
    // the incoming interest should bring the pin code
    std::string givenCode = readString(params.get(tlv_parameter_value));
    auto secret = request.m_challengeSecrets;
    if (currentTime - time::fromIsoString(request.m_challengeTp) >= m_secretLifetime) {
      return returnWithError(request, ErrorCode::OUT_OF_TIME, "Secret expired.");
    }
    if (givenCode == secret.get<std::string>(PARAMETER_KEY_CODE)) {
      _LOG_TRACE("Correct PIN code. Challenge succeeded.");
      return returnWithSuccess(request);
    }
    // check rest attempt times
    if (request.m_remainingTries > 1) {
      auto remainTime = m_secretLifetime - (currentTime - time::fromIsoString(request.m_challengeTp));
      _LOG_TRACE("Wrong PIN code provided. Remaining Tries - 1.");
      return returnWithNewChallengeStatus(request, WRONG_CODE, std::move(secret), request.m_remainingTries - 1, remainTime.count());
    }
    else {
      // run out times
      _LOG_TRACE("Wrong PIN code provided. Ran out tires. Challenge failed.");
      return returnWithError(request, ErrorCode::OUT_OF_TRIES, "Ran out tires.");
    }
  }
  return returnWithError(request, ErrorCode::INVALID_PARAMETER, "Unexpected status or challenge status");
}

// For Client
std::vector<std::tuple<std::string, std::string>>
ChallengePin::getRequestedParameterList(Status status, const std::string& challengeStatus)
{
  std::vector<std::tuple<std::string, std::string>> result;
  if (status == Status::BEFORE_CHALLENGE) {
    // do nothing
  }
  else if (status == Status::CHALLENGE && challengeStatus == NEED_CODE) {
    result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Please input your PIN code"));
  }
  else if (status == Status::CHALLENGE && challengeStatus == WRONG_CODE) {
    result.push_back(std::make_tuple(PARAMETER_KEY_CODE, "Incorrect PIN code, please try again"));
  }
  else {
    BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
  }
  return result;
}

Block
ChallengePin::genChallengeRequestTLV(Status status, const std::string& challengeStatus, std::vector<std::tuple<std::string, std::string>>&& params)
{
  Block request = makeEmptyBlock(tlv_encrypted_payload);
  if (status == Status::BEFORE_CHALLENGE) {
    request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
  }
  else if (status == Status::CHALLENGE && (challengeStatus == NEED_CODE || challengeStatus == WRONG_CODE)) {
    if (params.size() != 1 || std::get<0>(params[0]) != PARAMETER_KEY_CODE) {
      BOOST_THROW_EXCEPTION(std::runtime_error("Wrong parameter provided."));
    }
    request.push_back(makeStringBlock(tlv_selected_challenge, CHALLENGE_TYPE));
    request.push_back(makeStringBlock(tlv_parameter_key, PARAMETER_KEY_CODE));
    request.push_back(makeStringBlock(tlv_parameter_value, std::get<1>(params[0])));
  }
  else {
    BOOST_THROW_EXCEPTION(std::runtime_error("Unexpected status or challenge status."));
  }
  request.encode();
  return request;
}
}  // namespace ndncert
}  // namespace ndn
