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

#include "ndn-autoconfig/procedure.hpp"

#include "tests/tools/mock-nfd-mgmt-fixture.hpp"

#include <boost/logic/tribool.hpp>

namespace ndn::autoconfig::tests {

template<typename ProcedureClass>
class ProcedureFixture : public ::nfd::tests::MockNfdMgmtFixture
{
public:
  void
  initialize(const Options& options)
  {
    procedure = make_unique<ProcedureClass>(face, m_keyChain);
    procedure->initialize(options);
  }

  bool
  runOnce()
  {
    BOOST_ASSERT(procedure != nullptr);

    boost::logic::tribool result;
    procedure->onComplete.connectSingleShot([&] (bool res) { result = res; });
    procedure->runOnce();
    face.processEvents();

    BOOST_REQUIRE_MESSAGE(!boost::logic::indeterminate(result), "onComplete was not invoked");
    return bool(result);
  }

public:
  unique_ptr<ProcedureClass> procedure;
};

class DummyStage : public Stage
{
public:
  /** \param stageName stage name
   *  \param nCalls pointer to a variable which is incremented each time doStart is invoked
   *  \param result expected result, nullopt to cause a failued
   *  \param io io_context to asynchronously post the result
   */
  DummyStage(const std::string& stageName, int* nCalls,
             const std::optional<FaceUri>& result, boost::asio::io_context& io)
    : m_stageName(stageName)
    , m_nCalls(nCalls)
    , m_result(result)
    , m_io(io)
  {
  }

  const std::string&
  getName() const override
  {
    return m_stageName;
  }

private:
  void
  doStart() override
  {
    if (m_nCalls != nullptr) {
      ++(*m_nCalls);
    }

    boost::asio::post(m_io, [this] {
      if (m_result) {
        this->succeed(*m_result);
      }
      else {
        this->fail("DUMMY-STAGE-FAIL");
      }
    });
  }

private:
  std::string m_stageName;
  int* m_nCalls;
  std::optional<FaceUri> m_result;
  boost::asio::io_context& m_io;
};

/**
 * Two-stage Procedure where the first stage succeeds and the second stage fails,
 * but the second stage shouldn't be invoked after the first stage succeeds.
 */
class ProcedureSuccessFailure : public Procedure
{
public:
  ProcedureSuccessFailure(Face& face, KeyChain& keyChain)
    : Procedure(face, keyChain)
    , m_io(face.getIoContext())
  {
  }

private:
  void
  makeStages(const Options&) override
  {
    m_stages.push_back(make_unique<DummyStage>("first", &nCalls1, FaceUri("udp://188.7.60.95"), m_io));
    m_stages.push_back(make_unique<DummyStage>("second", &nCalls2, std::nullopt, m_io));
  }

public:
  int nCalls1 = 0;
  int nCalls2 = 0;

private:
  boost::asio::io_context& m_io;
};

/**
 * Two-stage Procedure where the first stage fails and the second stage succeeds.
 */
class ProcedureFailureSuccess : public Procedure
{
public:
  ProcedureFailureSuccess(Face& face, KeyChain& keyChain)
    : Procedure(face, keyChain)
    , m_io(face.getIoContext())
  {
  }

private:
  void
  makeStages(const Options&) override
  {
    m_stages.push_back(make_unique<DummyStage>("first", &nCalls1, std::nullopt, m_io));
    m_stages.push_back(make_unique<DummyStage>("second", &nCalls2, FaceUri("tcp://40.23.174.71"), m_io));
  }

public:
  int nCalls1 = 0;
  int nCalls2 = 0;

private:
  boost::asio::io_context& m_io;
};

BOOST_AUTO_TEST_SUITE(NdnAutoconfig)
BOOST_AUTO_TEST_SUITE(TestProcedure)

BOOST_FIXTURE_TEST_CASE(Normal, ProcedureFixture<ProcedureSuccessFailure>)
{
  this->initialize(Options{});

  int nRegisterNdn = 0, nRegisterLocalhopNfd = 0;
  this->processInterest = [&] (const Interest& interest) {
    auto req = parseCommand(interest, "/localhost/nfd/faces/create");
    if (req) {
      BOOST_REQUIRE(req->hasUri());
      BOOST_CHECK_EQUAL(req->getUri(), "udp4://188.7.60.95:6363");

      nfd::ControlParameters resp;
      resp.setFaceId(1178)
          .setUri("udp4://188.7.60.95:6363")
          .setLocalUri("udp4://110.69.164.68:23197")
          .setFacePersistency(nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT)
          .setFlags(0);
      this->succeedCommand(interest, resp);
      return;
    }

    req = parseCommand(interest, "/localhost/nfd/rib/register");
    if (req) {
      BOOST_REQUIRE(req->hasFaceId());
      BOOST_CHECK_EQUAL(req->getFaceId(), 1178);
      BOOST_REQUIRE(req->hasOrigin());
      BOOST_CHECK_EQUAL(req->getOrigin(), nfd::ROUTE_ORIGIN_AUTOCONF);
      BOOST_REQUIRE(req->hasName());
      if (req->getName() == "/") {
        ++nRegisterNdn;
      }
      else if (req->getName() == "/localhop/nfd") {
        ++nRegisterLocalhopNfd;
      }
      else {
        BOOST_ERROR("unexpected prefix registration " << req->getName());
      }

      nfd::ControlParameters resp;
      resp.setName(req->getName())
          .setFaceId(1178)
          .setOrigin(nfd::ROUTE_ORIGIN_AUTOCONF)
          .setCost(1)
          .setFlags(0);
      this->succeedCommand(interest, resp);
      return;
    }

    BOOST_FAIL("unrecognized command Interest " << interest);
  };

  BOOST_CHECK_EQUAL(this->runOnce(), true);
  BOOST_CHECK_EQUAL(procedure->nCalls1, 1);
  BOOST_CHECK_EQUAL(procedure->nCalls2, 0);
  BOOST_CHECK_EQUAL(nRegisterNdn, 1);
  BOOST_CHECK_EQUAL(nRegisterLocalhopNfd, 1);
}

BOOST_FIXTURE_TEST_CASE(ExistingFace, ProcedureFixture<ProcedureFailureSuccess>)
{
  this->initialize(Options{});

  int nRegisterDefault = 0, nRegisterLocalhopNfd = 0;
  this->processInterest = [&] (const Interest& interest) {
    auto req = parseCommand(interest, "/localhost/nfd/faces/create");
    if (req) {
      nfd::ControlParameters resp;
      resp.setFaceId(3146)
          .setUri("tcp4://40.23.174.71:6363")
          .setLocalUri("tcp4://34.213.69.67:14445")
          .setFacePersistency(nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT)
          .setFlags(0);
      this->failCommand(interest, 409, "conflict-409", resp);
      return;
    }

    req = parseCommand(interest, "/localhost/nfd/rib/register");
    if (req) {
      BOOST_REQUIRE(req->hasName());
      if (req->getName() == "/") {
        ++nRegisterDefault;
      }
      else if (req->getName() == "/localhop/nfd") {
        ++nRegisterLocalhopNfd;
      }
      else {
        BOOST_ERROR("unexpected prefix registration " << req->getName());
      }

      nfd::ControlParameters resp;
      resp.setName(req->getName())
          .setFaceId(3146)
          .setOrigin(nfd::ROUTE_ORIGIN_AUTOCONF)
          .setCost(1)
          .setFlags(0);
      this->succeedCommand(interest, resp);
      return;
    }

    BOOST_FAIL("unrecognized command Interest " << interest);
  };

  BOOST_CHECK_EQUAL(this->runOnce(), true);
  BOOST_CHECK_EQUAL(procedure->nCalls1, 1);
  BOOST_CHECK_EQUAL(procedure->nCalls2, 1);
  BOOST_CHECK_EQUAL(nRegisterDefault, 1);
  BOOST_CHECK_EQUAL(nRegisterLocalhopNfd, 1);
}

BOOST_AUTO_TEST_SUITE_END() // TestProcedure
BOOST_AUTO_TEST_SUITE_END() // NdnAutoconfig

} // namespace ndn::autoconfig::tests
