/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2016,  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 "face-manager-command-fixture.hpp"
#include "nfd-manager-common-fixture.hpp"

namespace nfd {
namespace tests {

BOOST_AUTO_TEST_SUITE(Mgmt)
BOOST_AUTO_TEST_SUITE(TestFaceManager)

class FaceManagerUpdateFixture : public FaceManagerCommandFixture
{
public:
  FaceManagerUpdateFixture()
    : faceId(0)
  {
  }

  ~FaceManagerUpdateFixture()
  {
    destroyFace();
  }

  void
  createFace(const std::string& uri = "tcp4://127.0.0.1:26363",
             ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
             bool enableLocalFields = false)
  {
    ControlParameters params;
    params.setUri(uri);
    params.setFacePersistency(persistency);
    params.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, enableLocalFields);

    Name commandName("/localhost/nfd/faces/create");
    commandName.append(params.wireEncode());
    auto command = makeInterest(commandName);
    m_keyChain.sign(*command);

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

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

        if (create.getBody().hasWire()) {
          ControlParameters faceParams(create.getBody());
          BOOST_REQUIRE(faceParams.hasFaceId());
          this->faceId = faceParams.getFaceId();
        }
        else {
          BOOST_FAIL("Face creation failed");
        }

        hasCallbackFired = true;
      });

    this->node1.face.receive(*command);
    this->advanceClocks(time::milliseconds(1), 5);

    BOOST_REQUIRE(hasCallbackFired);
  }

  void
  updateFace(const ControlParameters& requestParams,
             bool isSelfUpdating,
             const function<void(const ControlResponse& resp)>& checkResp)
  {
    Name commandName("/localhost/nfd/faces/update");
    commandName.append(requestParams.wireEncode());
    auto command = makeInterest(commandName);
    if (isSelfUpdating) {
      // Attach IncomingFaceIdTag to interest
      command->setTag(make_shared<lp::IncomingFaceIdTag>(faceId));
    }
    m_keyChain.sign(*command);

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

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

        hasCallbackFired = true;
      });

    this->node1.face.receive(*command);
    this->advanceClocks(time::milliseconds(1), 5);

    BOOST_CHECK(hasCallbackFired);
  }

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

    ControlParameters params;
    params.setFaceId(faceId);

    Name commandName("/localhost/nfd/faces/destroy");
    commandName.append(params.wireEncode());
    auto command = makeInterest(commandName);
    m_keyChain.sign(*command);

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

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

        faceId = 0;
        hasCallbackFired = true;
      });

    this->node1.face.receive(*command);
    this->advanceClocks(time::milliseconds(1), 5);

    BOOST_CHECK(hasCallbackFired);
  }

public:
  FaceId faceId;
};

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());
  });
}

// TODO #3232: Expected failure until FacePersistency updating implemented
BOOST_AUTO_TEST_CASE(UpdatePersistency)
{
  createFace();

  ControlParameters requestParams;
  requestParams.setFaceId(faceId);
  requestParams.setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);

  updateFace(requestParams, false, [] (const ControlResponse& actual) {
    ControlResponse expected(409, "Invalid fields specified");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

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

      BOOST_REQUIRE(actualParams.hasFacePersistency());
      BOOST_CHECK_EQUAL(actualParams.getFacePersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
    }
    else {
      BOOST_ERROR("Response does not contain ControlParameters");
    }
  });
}

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

  boost::asio::ip::address_v4
  getIpAddress()
  {
    return boost::asio::ip::address_v4::from_string("127.0.0.1");
  }

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

  bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  bool
  getLocalFieldsEnabled()
  {
    return true;
  }

  bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  bool
  shouldHaveWire()
  {
    return false;
  }
};

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

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

  bool
  getInitLocalFieldsEnabled()
  {
    return true;
  }

  bool
  getLocalFieldsEnabled()
  {
    return false;
  }

  bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  bool
  shouldHaveWire()
  {
    return false;
  }
};

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

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

  bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  bool
  getLocalFieldsEnabled()
  {
    return true;
  }

  bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  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:
  std::string
  getUri()
  {
    return "udp4://127.0.0.1:26363";
  }

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

  bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  bool
  getLocalFieldsEnabled()
  {
    return false;
  }

  bool
  getLocalFieldsEnabledMask()
  {
    return true;
  }

  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:
  std::string
  getUri()
  {
    return "udp4://127.0.0.1:26363";
  }

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

  bool
  getInitLocalFieldsEnabled()
  {
    return false;
  }

  bool
  getLocalFieldsEnabled()
  {
    return true;
  }

  bool
  getLocalFieldsEnabledMask()
  {
    return false;
  }

  bool
  shouldHaveWire()
  {
    return false;
  }
};

namespace mpl = boost::mpl;

typedef mpl::vector<mpl::pair<TcpLocalFieldsEnable, CommandSuccess>,
                    mpl::pair<TcpLocalFieldsDisable, CommandSuccess>,
                    mpl::pair<UdpLocalFieldsEnable, CommandFailure<409>>,
                    mpl::pair<UdpLocalFieldsDisable, CommandSuccess>,
                    mpl::pair<UdpLocalFieldsEnableNoMaskBit, CommandSuccess>> LocalFieldFaces;

BOOST_AUTO_TEST_CASE_TEMPLATE(UpdateLocalFields, T, LocalFieldFaces)
{
  typedef typename T::first TestType;
  typedef typename T::second ResultType;

  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().getCode(), "");
    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
    BOOST_TEST_MESSAGE(actual.getText());

    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(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 tests
} // namespace nfd
