/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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.
 *
 * NFD 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 a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef NFD_TESTS_TOOLS_MOCK_NFD_MGMT_FIXTURE_HPP
#define NFD_TESTS_TOOLS_MOCK_NFD_MGMT_FIXTURE_HPP

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

#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
#include <ndn-cxx/mgmt/nfd/control-response.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>

#include <boost/concept/assert.hpp>

namespace nfd::tests {

using ndn::nfd::ControlParameters;

/**
 * \brief Fixture to emulate NFD management.
 */
class MockNfdMgmtFixture : public IoFixture, public KeyChainFixture
{
protected:
  MockNfdMgmtFixture()
    : face(m_io, m_keyChain,
           {true, false, std::bind(&MockNfdMgmtFixture::processEventsOverride, this, _1)})
  {
    face.onSendInterest.connect([this] (const Interest& interest) {
      if (processInterest) {
        m_io.post([=] { processInterest(interest); });
      }
    });
  }

protected: // ControlCommand
  /** \brief check the Interest is a command with specified prefix
   *  \retval nullopt last Interest is not the expected command
   *  \return command parameters
   */
  static std::optional<ControlParameters>
  parseCommand(const Interest& interest, const Name& expectedPrefix)
  {
    if (!expectedPrefix.isPrefixOf(interest.getName())) {
      return std::nullopt;
    }
    return ControlParameters(interest.getName().at(expectedPrefix.size()).blockFromValue());
  }

  /** \brief send successful response to a command Interest
   */
  void
  succeedCommand(const Interest& interest, const ControlParameters& parameters)
  {
    this->sendCommandReply(interest, 200, "OK", parameters.wireEncode());
  }

  /** \brief send failure response to a command Interest
   */
  void
  failCommand(const Interest& interest, uint32_t code, const std::string& text)
  {
    this->sendCommandReply(interest, {code, text});
  }

  /** \brief send failure response to a command Interest
   */
  void
  failCommand(const Interest& interest, uint32_t code, const std::string& text, const ControlParameters& body)
  {
    this->sendCommandReply(interest, code, text, body.wireEncode());
  }

protected: // StatusDataset
  /** \brief send an empty dataset in reply to StatusDataset request
   *  \param prefix dataset prefix without version and segment
   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
   */
  void
  sendEmptyDataset(const Name& prefix)
  {
    this->sendDatasetReply(prefix, span<uint8_t>{});
  }

  /** \brief send one WireEncodable in reply to StatusDataset request
   *  \param prefix dataset prefix without version and segment
   *  \param payload payload block
   *  \note payload must fit in one Data
   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
   */
  template<typename T>
  void
  sendDataset(const Name& prefix, const T& payload)
  {
    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T>));

    this->sendDatasetReply(prefix, payload.wireEncode());
  }

  /** \brief send two WireEncodables in reply to StatusDataset request
   *  \param prefix dataset prefix without version and segment
   *  \param payload1 first vector item
   *  \param payload2 second vector item
   *  \note all payloads must fit in one Data
   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
   */
  template<typename T1, typename T2>
  void
  sendDataset(const Name& prefix, const T1& payload1, const T2& payload2)
  {
    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T1>));
    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T2>));

    ndn::encoding::EncodingBuffer buffer;
    payload2.wireEncode(buffer);
    payload1.wireEncode(buffer);

    this->sendDatasetReply(prefix, buffer);
  }

private:
  virtual void
  processEventsOverride(time::milliseconds timeout)
  {
    if (timeout <= 0_ms) {
      // give enough time to finish execution
      timeout = 30_s;
    }
    this->advanceClocks(100_ms, timeout);
  }

  void
  sendCommandReply(const Interest& interest, const ndn::nfd::ControlResponse& resp)
  {
    auto data = makeData(interest.getName());
    data->setContent(resp.wireEncode());
    face.receive(*data);
  }

  void
  sendCommandReply(const Interest& interest, uint32_t code, const std::string& text,
                   const Block& body)
  {
    this->sendCommandReply(interest, ndn::nfd::ControlResponse(code, text).setBody(body));
  }

  /** \brief send a payload in reply to StatusDataset request
   *  \param name dataset prefix without version and segment
   *  \param contentArgs passed to Data::setContent
   */
  template<typename ...ContentArgs>
  void
  sendDatasetReply(Name name, ContentArgs&&... contentArgs)
  {
    name.appendVersion().appendSegment(0);

    // These warnings assist in debugging when nfdc does not receive StatusDataset.
    // They usually indicate a misspelled prefix or incorrect timing in the test case.
    if (face.sentInterests.empty()) {
      BOOST_WARN_MESSAGE(false, "no Interest expressed");
    }
    else {
      BOOST_WARN_MESSAGE(face.sentInterests.back().getName().isPrefixOf(name),
                         "last Interest " << face.sentInterests.back().getName() <<
                         " cannot be satisfied by this Data " << name);
    }

    auto data = make_shared<Data>(name);
    data->setFreshnessPeriod(1_s);
    data->setFinalBlock(name[-1]);
    data->setContent(std::forward<ContentArgs>(contentArgs)...);
    this->signDatasetReply(*data);
    face.receive(*data);
  }

  virtual void
  signDatasetReply(Data& data)
  {
    signData(data);
  }

protected:
  ndn::util::DummyClientFace face;
  std::function<void(const Interest&)> processInterest;
};

} // namespace nfd::tests

/** \brief require the command in \p interest has expected prefix
 *  \note This must be used in processInterest lambda, and the Interest must be named 'interest'.
 *  \return ControlParameters, or nullopt if \p interest does match \p expectedPrefix
 */
#define MOCK_NFD_MGMT_REQUIRE_COMMAND_IS(expectedPrefix) \
  [interest] { \
    auto params = parseCommand(interest, (expectedPrefix)); \
    BOOST_REQUIRE_MESSAGE(params, "Interest " << interest.getName() << \
                          " does not match command prefix " << (expectedPrefix)); \
    return *params; \
  } ()

#endif // NFD_TESTS_TOOLS_MOCK_NFD_MGMT_FIXTURE_HPP
