/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2020 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_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
#define NDN_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/identity-management-time-fixture.hpp"

#include <boost/lexical_cast.hpp>

namespace ndn {
namespace security {
inline namespace v2 {
namespace tests {

template<class ValidationPolicy, class CertificateFetcher = CertificateFetcherFromNetwork>
class ValidatorFixture : public ndn::tests::IdentityManagementTimeFixture
{
public:
  ValidatorFixture()
    : face(io, {true, true})
    , validator(make_unique<ValidationPolicy>(), make_unique<CertificateFetcher>(face))
    , policy(static_cast<ValidationPolicy&>(validator.getPolicy()))
    , cache(100_days)
    , lastError(ValidationError::Code::NO_ERROR)
  {
    processInterest = [this] (const Interest& interest) {
      auto cert = cache.find(interest);
      if (cert != nullptr) {
        face.receive(*cert);
      }
    };
  }

  virtual
  ~ValidatorFixture() = default;

  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&) {
        ++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);
  }

  void
  mockNetworkOperations()
  {
    util::signal::ScopedConnection connection = face.onSendInterest.connect([this] (const Interest& interest) {
        if (processInterest != nullptr) {
          io.post(bind(processInterest, interest));
        }
      });
    advanceClocks(time::milliseconds(s_mockPeriod), s_mockTimes);
  }

  /** \brief undo clock advancement of mockNetworkOperations
   */
  void
  rewindClockAfterValidation()
  {
    this->systemClock->advance(time::milliseconds(s_mockPeriod * s_mockTimes * -1));
  }

public:
  util::DummyClientFace face;
  std::function<void(const Interest& interest)> processInterest;
  Validator validator;
  ValidationPolicy& policy;

  CertificateCache cache;
  ValidationError lastError;

private:
  const static int s_mockPeriod;
  const static int s_mockTimes;
};

template<class ValidationPolicy, class CertificateFetcher>
const int ValidatorFixture<ValidationPolicy, CertificateFetcher>::s_mockPeriod = 250;

template<class ValidationPolicy, class CertificateFetcher>
const int ValidatorFixture<ValidationPolicy, CertificateFetcher>::s_mockTimes = 200;

template<class ValidationPolicy, class CertificateFetcher = CertificateFetcherFromNetwork>
class HierarchicalValidatorFixture : public ValidatorFixture<ValidationPolicy, CertificateFetcher>
{
public:
  HierarchicalValidatorFixture()
  {
    identity = this->addIdentity("/Security/ValidatorFixture");
    subIdentity = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
    subSelfSignedIdentity = this->addIdentity("/Security/ValidatorFixture/Sub1/Sub2");
    otherIdentity = this->addIdentity("/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());
  }

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

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

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

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

private:
  void
  verifyOriginalPacket(const Certificate& trustedCert) override
  {
    // do nothing
  }

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


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

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

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

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

  static Name
  makeName(Name name, KeyChain& keyChain)
  {
    Interest interest(name);
    interest.setCanBePrefix(false);
    SigningInfo params;
    params.setSignedInterestFormat(SignedInterestFormat::V02);
    keyChain.sign(interest, params);
    return interest.getName();
  }

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

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

  static Name
  makeName(Name name, KeyChain& keyChain)
  {
    Interest interest(name);
    interest.setCanBePrefix(false);
    SigningInfo params;
    params.setSignedInterestFormat(SignedInterestFormat::V03);
    keyChain.sign(interest, params);
    return interest.getName();
  }

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

} // namespace tests
} // inline namespace v2
} // namespace security
} // namespace ndn

#endif // NDN_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
