/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2024,  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 "mgmt/face-manager.hpp"
#include "face/generic-link-service.hpp"

#include "face-manager-command-fixture.hpp"
#include "tests/daemon/face/dummy-transport.hpp"

#include <ndn-cxx/lp/tags.hpp>

#include <boost/logic/tribool.hpp>
#include <boost/mp11/list.hpp>
#include <thread>

namespace nfd::tests {

BOOST_AUTO_TEST_SUITE(Mgmt)
BOOST_AUTO_TEST_SUITE(TestFaceManager)

class FaceManagerUpdateFixture : public FaceManagerCommandFixture
{
public:
  ~FaceManagerUpdateFixture() override
  {
    destroyFace();
  }

  void
  createFace(const std::string& uri = "tcp4://127.0.0.1:26363",
             ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
             std::optional<time::nanoseconds> baseCongestionMarkingInterval = std::nullopt,
             std::optional<uint64_t> defaultCongestionThreshold = std::nullopt,
             bool enableLocalFields = false,
             bool enableReliability = false,
             boost::logic::tribool enableCongestionMarking = boost::logic::indeterminate)
  {
    ControlParameters params;
    params.setUri(uri);
    params.setFacePersistency(persistency);

    if (baseCongestionMarkingInterval) {
      params.setBaseCongestionMarkingInterval(*baseCongestionMarkingInterval);
    }

    if (defaultCongestionThreshold) {
      params.setDefaultCongestionThreshold(*defaultCongestionThreshold);
    }

    params.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, enableLocalFields);
    params.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, enableReliability);

    if (!boost::logic::indeterminate(enableCongestionMarking)) {
      params.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, bool(enableCongestionMarking));
    }

    createFace(params);
  }

  void
  createFace(const ControlParameters& createParams, bool isForOnDemandFace = false)
  {
    Interest req = makeControlCommandRequest("/localhost/nfd/faces/create", createParams);

    // if this creation if for on-demand face then create it on node2
    FaceManagerCommandNode& target = isForOnDemandFace ? this->node2 : this->node1;

    bool hasCallbackFired = false;
    signal::ScopedConnection connection = target.face.onSendData.connect(
      [&, req, isForOnDemandFace, this] (const Data& response) {
        if (!req.getName().isPrefixOf(response.getName())) {
          return;
        }

        ControlResponse create(response.getContent().blockFromValue());
        BOOST_REQUIRE_EQUAL(create.getCode(), 200);
        BOOST_REQUIRE(create.getBody().hasWire());

        ControlParameters faceParams(create.getBody());
        BOOST_REQUIRE(faceParams.hasFaceId());
        this->faceId = faceParams.getFaceId();

        hasCallbackFired = true;

        if (isForOnDemandFace) {
          auto face = target.faceTable.get(static_cast<FaceId>(this->faceId));
          // to force creation of on-demand face
          face->sendInterest(*makeInterest("/hello/world"));
        }
      });

    target.face.receive(req);
    advanceClocks(1_ms, 5);

    if (isForOnDemandFace) {
      std::this_thread::sleep_for(std::chrono::milliseconds(100)); // allow wallclock time for socket IO
      advanceClocks(1_ms, 5); // let node1 accept Interest and create on-demand face
    }

    BOOST_REQUIRE(hasCallbackFired);
  }

  void
  updateFace(const ControlParameters& requestParams,
             bool isSelfUpdating,
             const std::function<void(const ControlResponse& resp)>& checkResp)
  {
    Interest req = makeControlCommandRequest("/localhost/nfd/faces/update", requestParams);
    if (isSelfUpdating) {
      // Attach IncomingFaceIdTag to interest
      req.setTag(make_shared<lp::IncomingFaceIdTag>(faceId));
    }

    bool hasCallbackFired = false;
    signal::ScopedConnection connection = this->node1.face.onSendData.connect(
      [req, &hasCallbackFired, &checkResp] (const Data& response) {
        if (!req.getName().isPrefixOf(response.getName())) {
          return;
        }

        ControlResponse actual(response.getContent().blockFromValue());
        checkResp(actual);

        hasCallbackFired = true;
      });

    this->node1.face.receive(req);
    advanceClocks(1_ms, 5);
    BOOST_REQUIRE(hasCallbackFired);
  }

private:
  void
  destroyFace()
  {
    if (faceId == 0) {
      return;
    }

    ControlParameters params;
    params.setFaceId(faceId);
    Interest req = makeControlCommandRequest("/localhost/nfd/faces/destroy", params);

    bool hasCallbackFired = false;
    signal::ScopedConnection connection = this->node1.face.onSendData.connect(
      [this, req, &hasCallbackFired] (const Data& response) {
        if (!req.getName().isPrefixOf(response.getName())) {
          return;
        }

        ControlResponse destroy(response.getContent().blockFromValue());
        BOOST_CHECK_EQUAL(destroy.getCode(), 200);

        faceId = 0;
        hasCallbackFired = true;
      });

    this->node1.face.receive(req);
    advanceClocks(1_ms, 5);
    BOOST_REQUIRE(hasCallbackFired);
  }

protected:
  FaceId faceId = 0;
};

BOOST_FIXTURE_TEST_SUITE(UpdateFace, FaceManagerUpdateFixture)

BOOST_AUTO_TEST_CASE(FaceDoesNotExist)
{
  ControlParameters requestParams;
  requestParams.setFaceId(65535);

  updateFace(requestParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(404, "Specified face does not exist");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());
  });
}

using UpdatePersistencyTests = boost::mp11::mp_list<
  boost::mp11::mp_list<DummyTransportBase<true>, CommandSuccess>,
  boost::mp11::mp_list<DummyTransportBase<false>, CommandFailure<409>>
>;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(UpdatePersistency, T, UpdatePersistencyTests, FaceManagerUpdateFixture)
{
  using TransportType = boost::mp11::mp_first<T>;
  using ResultType = boost::mp11::mp_second<T>;

  auto face = make_shared<face::Face>(make_unique<face::GenericLinkService>(),
                                      make_unique<TransportType>());
  this->node1.faceTable.add(face);

  auto parameters = ControlParameters()
    .setFaceId(face->getId())
    .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);

  updateFace(parameters, false, [] (const ControlResponse& actual) {
      BOOST_TEST_MESSAGE(actual.getText());
      BOOST_CHECK_EQUAL(actual.getCode(), ResultType::getExpected().getCode());

      // the response for either 200 or 409 will have a content body
      BOOST_REQUIRE(actual.getBody().hasWire());

      ControlParameters resp;
      resp.wireDecode(actual.getBody());
      BOOST_CHECK_EQUAL(resp.getFacePersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
  });
}

BOOST_AUTO_TEST_CASE(UpdateMtu)
{
  createFace("udp4://127.0.0.1:26363");

  ControlParameters validParams;
  validParams.setFaceId(faceId);
  validParams.setMtu(4000);

  ControlParameters mtuTooLow;
  mtuTooLow.setFaceId(faceId);
  mtuTooLow.setMtu(63);

  updateFace(validParams, false, [] (const ControlResponse& actual) {
    BOOST_CHECK_EQUAL(actual.getCode(), 200);
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(actualParams.hasFaceId());
      BOOST_REQUIRE(actualParams.hasMtu());
      // Check for changed MTU
      BOOST_CHECK_EQUAL(actualParams.getMtu(), 4000);
    }
    else {
      BOOST_ERROR("Valid: Response does not contain ControlParameters");
    }
  });

  updateFace(mtuTooLow, false, [] (const ControlResponse& actual) {
    BOOST_CHECK_EQUAL(actual.getCode(), 409);
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(!actualParams.hasFaceId());
      BOOST_REQUIRE(actualParams.hasMtu());
      // Check for returned invalid parameter
      BOOST_CHECK_EQUAL(actualParams.getMtu(), 63);
    }
    else {
      BOOST_ERROR("Too low: Response does not contain ControlParameters");
    }
  });
}

BOOST_AUTO_TEST_CASE(UpdateMtuUnsupportedFace)
{
  createFace("tcp4://127.0.0.1:26363");

  ControlParameters updateParams;
  updateParams.setFaceId(faceId);
  updateParams.setMtu(4000);

  updateFace(updateParams, false, [] (const ControlResponse& actual) {
    BOOST_CHECK_EQUAL(actual.getCode(), 409);
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(!actualParams.hasFaceId());
      BOOST_REQUIRE(actualParams.hasMtu());
      // Check for returned invalid parameter
      BOOST_CHECK_EQUAL(actualParams.getMtu(), 4000);
    }
    else {
      BOOST_ERROR("Response does not contain ControlParameters");
    }
  });
}

class TcpLocalFieldsEnable
{
public:
  static std::string
  getUri()
  {
    return "tcp4://127.0.0.1:26363";
  }

  static constexpr ndn::nfd::FacePersistency
  getPersistency()
  {
    return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
  }

  static constexpr bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  static constexpr bool
  getLocalFieldsEnabled()
  {
    return true;
  }

  static constexpr bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  static constexpr bool
  shouldHaveWire()
  {
    return false;
  }
};

class TcpLocalFieldsDisable
{
public:
  static std::string
  getUri()
  {
    return "tcp4://127.0.0.1:26363";
  }

  static constexpr ndn::nfd::FacePersistency
  getPersistency()
  {
    return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
  }

  static constexpr bool
  getInitLocalFieldsEnabled()
  {
    return true;
  }

  static constexpr bool
  getLocalFieldsEnabled()
  {
    return false;
  }

  static constexpr bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  static constexpr bool
  shouldHaveWire()
  {
    return false;
  }
};

// UDP faces are non-local by definition
class UdpLocalFieldsEnable
{
public:
  static std::string
  getUri()
  {
    return "udp4://127.0.0.1:26363";
  }

  static constexpr ndn::nfd::FacePersistency
  getPersistency()
  {
    return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
  }

  static constexpr bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  static constexpr bool
  getLocalFieldsEnabled()
  {
    return true;
  }

  static constexpr bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  static constexpr bool
  shouldHaveWire()
  {
    return true;
  }
};

// UDP faces are non-local by definition
// In this test case, attempt to disable local fields on face with local fields already disabled
class UdpLocalFieldsDisable
{
public:
  static std::string
  getUri()
  {
    return "udp4://127.0.0.1:26363";
  }

  static constexpr ndn::nfd::FacePersistency
  getPersistency()
  {
    return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
  }

  static constexpr bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  static constexpr bool
  getLocalFieldsEnabled()
  {
    return false;
  }

  static constexpr bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  static constexpr bool
  shouldHaveWire()
  {
    return false;
  }
};

// In this test case, set Flags to enable local fields on non-local face, but exclude local fields
// from Mask. This test case will pass as no action is taken due to the missing Mask bit.
class UdpLocalFieldsEnableNoMaskBit
{
public:
  static std::string
  getUri()
  {
    return "udp4://127.0.0.1:26363";
  }

  static constexpr ndn::nfd::FacePersistency
  getPersistency()
  {
    return ndn::nfd::FACE_PERSISTENCY_PERSISTENT;
  }

  static constexpr bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  static constexpr bool
  getLocalFieldsEnabled()
  {
    return true;
  }

  static constexpr bool
  getLocalFieldsEnabledMask()
  {
    return false;
  }

  static constexpr bool
  shouldHaveWire()
  {
    return false;
  }
};

using LocalFieldFaces = boost::mp11::mp_list<
  boost::mp11::mp_list<TcpLocalFieldsEnable, CommandSuccess>,
  boost::mp11::mp_list<TcpLocalFieldsDisable, CommandSuccess>,
  boost::mp11::mp_list<UdpLocalFieldsEnable, CommandFailure<409>>,
  boost::mp11::mp_list<UdpLocalFieldsDisable, CommandSuccess>,
  boost::mp11::mp_list<UdpLocalFieldsEnableNoMaskBit, CommandSuccess>
>;

BOOST_AUTO_TEST_CASE_TEMPLATE(UpdateLocalFields, T, LocalFieldFaces)
{
  using TestType = boost::mp11::mp_first<T>;
  using ResultType = boost::mp11::mp_second<T>;

  createFace(TestType::getUri(), TestType::getPersistency(), {}, {},
             TestType::getInitLocalFieldsEnabled());

  ControlParameters requestParams;
  requestParams.setFaceId(faceId);
  requestParams.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, TestType::getLocalFieldsEnabled());
  if (!TestType::getLocalFieldsEnabledMask()) {
    requestParams.unsetFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
  }

  updateFace(requestParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(ResultType::getExpected());
    BOOST_TEST_MESSAGE(actual.getText());
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());

    if (TestType::shouldHaveWire() && actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(!actualParams.hasFacePersistency());
      BOOST_CHECK(actualParams.hasFlags());
      BOOST_CHECK(actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
      BOOST_CHECK(actualParams.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
    }
  });
}

BOOST_AUTO_TEST_CASE(UpdateLocalFieldsEnableDisable)
{
  createFace();

  ControlParameters enableParams;
  enableParams.setFaceId(faceId);
  enableParams.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true);

  ControlParameters disableParams;
  disableParams.setFaceId(faceId);
  disableParams.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, false);

  updateFace(enableParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(200, "OK");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(actualParams.hasFaceId());
      BOOST_CHECK(actualParams.hasFacePersistency());
      BOOST_REQUIRE(actualParams.hasFlags());
      // Check if flags indicate local fields enabled
      BOOST_CHECK(actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
    }
    else {
      BOOST_ERROR("Enable: Response does not contain ControlParameters");
    }
  });

  updateFace(disableParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(200, "OK");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(actualParams.hasFaceId());
      BOOST_CHECK(actualParams.hasFacePersistency());
      BOOST_REQUIRE(actualParams.hasFlags());
      // Check if flags indicate local fields disabled
      BOOST_CHECK(!actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
    }
    else {
      BOOST_ERROR("Disable: Response does not contain ControlParameters");
    }
  });
}

BOOST_AUTO_TEST_CASE(UpdateReliabilityEnableDisable)
{
  createFace("udp4://127.0.0.1:26363");

  ControlParameters enableParams;
  enableParams.setFaceId(faceId);
  enableParams.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true);

  ControlParameters disableParams;
  disableParams.setFaceId(faceId);
  disableParams.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, false);

  updateFace(enableParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(200, "OK");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(actualParams.hasFaceId());
      BOOST_CHECK(actualParams.hasFacePersistency());
      BOOST_REQUIRE(actualParams.hasFlags());
      // Check if flags indicate reliability enabled
      BOOST_CHECK(actualParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED));
    }
    else {
      BOOST_ERROR("Enable: Response does not contain ControlParameters");
    }
  });

  updateFace(disableParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(200, "OK");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(actualParams.hasFaceId());
      BOOST_CHECK(actualParams.hasFacePersistency());
      BOOST_REQUIRE(actualParams.hasFlags());
      // Check if flags indicate reliability disabled
      BOOST_CHECK(!actualParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED));
    }
    else {
      BOOST_ERROR("Disable: Response does not contain ControlParameters");
    }
  });
}

BOOST_AUTO_TEST_CASE(UpdateCongestionMarkingEnableDisable)
{
  createFace("udp4://127.0.0.1:26363");

  ControlParameters enableParams;
  enableParams.setFaceId(faceId);
  enableParams.setBaseCongestionMarkingInterval(50_ms);
  enableParams.setDefaultCongestionThreshold(10000);
  enableParams.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true);

  ControlParameters disableParams;
  disableParams.setFaceId(faceId);
  disableParams.setBaseCongestionMarkingInterval(70_ms);
  disableParams.setDefaultCongestionThreshold(5000);
  disableParams.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, false);

  updateFace(enableParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(200, "OK");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(actualParams.hasFaceId());
      BOOST_CHECK(actualParams.hasFacePersistency());
      // Check that congestion marking parameters changed
      BOOST_REQUIRE(actualParams.hasBaseCongestionMarkingInterval());
      BOOST_CHECK_EQUAL(actualParams.getBaseCongestionMarkingInterval(), 50_ms);
      BOOST_REQUIRE(actualParams.hasDefaultCongestionThreshold());
      BOOST_CHECK_EQUAL(actualParams.getDefaultCongestionThreshold(), 10000);
      BOOST_REQUIRE(actualParams.hasFlags());
      // Check if flags indicate congestion marking enabled
      BOOST_CHECK(actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
    }
    else {
      BOOST_ERROR("Enable: Response does not contain ControlParameters");
    }
  });

  updateFace(disableParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(200, "OK");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

    if (actual.getBody().hasWire()) {
      ControlParameters actualParams(actual.getBody());

      BOOST_CHECK(actualParams.hasFaceId());
      BOOST_CHECK(actualParams.hasFacePersistency());
      // Check that congestion marking parameters changed, even though feature disabled
      BOOST_REQUIRE(actualParams.hasBaseCongestionMarkingInterval());
      BOOST_CHECK_EQUAL(actualParams.getBaseCongestionMarkingInterval(), 70_ms);
      BOOST_REQUIRE(actualParams.hasDefaultCongestionThreshold());
      BOOST_CHECK_EQUAL(actualParams.getDefaultCongestionThreshold(), 5000);
      BOOST_REQUIRE(actualParams.hasFlags());
      // Check if flags indicate marking disabled
      BOOST_CHECK(!actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
    }
    else {
      BOOST_ERROR("Disable: Response does not contain ControlParameters");
    }
  });
}

BOOST_AUTO_TEST_CASE(SelfUpdating)
{
  createFace();

  // Send a command that does nothing (will return 200) and does not contain a FaceId
  ControlParameters sentParams;

  updateFace(sentParams, true, [] (const ControlResponse& actual) {
    ControlResponse expected(200, "OK");
    BOOST_REQUIRE_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());
  });
}

BOOST_AUTO_TEST_SUITE_END() // UpdateFace
BOOST_AUTO_TEST_SUITE_END() // TestFaceManager
BOOST_AUTO_TEST_SUITE_END() // Mgmt

} // namespace nfd::tests
