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

#ifndef NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
#define NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP

#include "ndn-cxx/security/validator.hpp"
#include "ndn-cxx/security/certificate-fetcher-from-network.hpp"
#include "ndn-cxx/util/dummy-client-face.hpp"

#include "tests/boost-test.hpp"
#include "tests/unit/io-key-chain-fixture.hpp"

#include <boost/lexical_cast.hpp>

namespace ndn::tests {

using ndn::security::Certificate;
using ndn::security::Identity;
using ndn::security::ValidationError;

class ValidatorFixtureBase : public IoKeyChainFixture
{
protected:
  ValidatorFixtureBase();

  void
  mockNetworkOperations();

  /**
   * @brief Undo clock advancement of mockNetworkOperations()
   */
  void
  rewindClockAfterValidation();

  /**
   * @brief Issues a certificate for @p subIdentityName signed by @p issuer
   *
   * If the identity does not exist, it is created.
   * A new key is generated as the default key for the identity.
   * A default certificate for the key is signed by the issuer using its default certificate.
   *
   * @return The sub-identity
   */
  Identity
  addSubCertificate(const Name& subIdentityName, const Identity& issuer);

protected:
  DummyClientFace face{m_io, {true, true}};
  std::function<void(const Interest&)> processInterest;
  security::CertificateCache cache{100_days};
  ValidationError lastError{ValidationError::NO_ERROR};

private:
  static constexpr time::milliseconds s_mockPeriod{250};
  static constexpr int s_mockTimes{200};
};

template<class ValidationPolicyT, class CertificateFetcherT = security::CertificateFetcherFromNetwork>
class ValidatorFixture : public ValidatorFixtureBase
{
protected:
  ValidatorFixture()
    : validator(make_unique<ValidationPolicyT>(), make_unique<CertificateFetcherT>(face))
    , policy(static_cast<ValidationPolicyT&>(validator.getPolicy()))
  {
  }

  template<class Packet>
  void
  validate(const Packet& packet, const std::string& msg, bool expectSuccess, int line)
  {
    std::string detailedInfo = msg + " on line " + to_string(line);
    size_t nCallbacks = 0;
    this->validator.validate(packet,
      [&] (const Packet&) {
        lastError = ValidationError::NO_ERROR;
        ++nCallbacks;
        BOOST_CHECK_MESSAGE(expectSuccess,
                            (expectSuccess ? "OK: " : "FAILED: ") + detailedInfo);
      },
      [&] (const Packet&, const ValidationError& error) {
        lastError = error;
        ++nCallbacks;
        BOOST_CHECK_MESSAGE(!expectSuccess,
                            (!expectSuccess ? "OK: " : "FAILED: ") + detailedInfo +
                            (expectSuccess ? " (" + boost::lexical_cast<std::string>(error) + ")" : ""));
      });

    mockNetworkOperations();
    BOOST_CHECK_EQUAL(nCallbacks, 1);
  }

protected:
  security::Validator validator;
  ValidationPolicyT& policy;
};

template<class ValidationPolicyT, class CertificateFetcherT = security::CertificateFetcherFromNetwork>
class HierarchicalValidatorFixture : public ValidatorFixture<ValidationPolicyT, CertificateFetcherT>
{
protected:
  HierarchicalValidatorFixture()
  {
    identity = this->m_keyChain.createIdentity("/Security/ValidatorFixture");
    subIdentity = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
    subSelfSignedIdentity = this->m_keyChain.createIdentity("/Security/ValidatorFixture/Sub1/Sub2");
    otherIdentity = this->m_keyChain.createIdentity("/Security/OtherIdentity");

    this->validator.loadAnchor("", Certificate(identity.getDefaultKey().getDefaultCertificate()));

    this->cache.insert(identity.getDefaultKey().getDefaultCertificate());
    this->cache.insert(subIdentity.getDefaultKey().getDefaultCertificate());
    this->cache.insert(subSelfSignedIdentity.getDefaultKey().getDefaultCertificate());
    this->cache.insert(otherIdentity.getDefaultKey().getDefaultCertificate());
  }

protected:
  Identity identity;
  Identity subIdentity;
  Identity subSelfSignedIdentity;
  Identity otherIdentity;
};

#define VALIDATE_SUCCESS(packet, message) this->validate(packet, message, true, __LINE__)
#define VALIDATE_FAILURE(packet, message) this->validate(packet, message, false, __LINE__)

class DummyValidationState : public security::ValidationState
{
public:
  ~DummyValidationState() override
  {
    m_outcome = false;
  }

  void
  fail(const ValidationError&) override
  {
    m_outcome = false;
  }

private:
  void
  verifyOriginalPacket(const std::optional<Certificate>&) override
  {
    // do nothing
  }

  void
  bypassValidation() override
  {
    // do nothing
  }
};

struct DataPkt
{
  static constexpr uint32_t
  getType()
  {
    return tlv::Data;
  }

  static Name
  makeName(Name name, KeyChain&)
  {
    return name;
  }

  static Data
  makePacket(const Name& name)
  {
    return Data(name);
  }

  static shared_ptr<security::ValidationState>
  makeState()
  {
    return make_shared<DummyValidationState>();
  }
};

struct InterestV02Pkt
{
  static constexpr uint32_t
  getType()
  {
    return tlv::Interest;
  }

  static Name
  makeName(Name name, KeyChain& keyChain);

  static Interest
  makePacket(const Name& name)
  {
    return Interest(name);
  }

  static shared_ptr<security::ValidationState>
  makeState()
  {
    auto state = make_shared<DummyValidationState>();
    state->setTag(make_shared<security::SignedInterestFormatTag>(security::SignedInterestFormat::V02));
    return state;
  }
};

struct InterestV03Pkt
{
  static constexpr uint32_t
  getType()
  {
    return tlv::Interest;
  }

  static Name
  makeName(Name name, KeyChain& keyChain);

  static Interest
  makePacket(const Name& name)
  {
    return Interest(name);
  }

  static shared_ptr<security::ValidationState>
  makeState()
  {
    auto state = make_shared<DummyValidationState>();
    state->setTag(make_shared<security::SignedInterestFormatTag>(security::SignedInterestFormat::V03));
    return state;
  }
};

} // namespace ndn::tests

#endif // NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
