/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2015,  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 "rib/rib-manager.hpp"
#include <ndn-cxx/management/nfd-face-status.hpp>
#include "rib/rib-status-publisher-common.hpp"

#include "tests/test-common.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>

namespace nfd {
namespace rib {
namespace tests {

using namespace nfd::tests;

class RibManagerFixture : public UnitTestTimeFixture
{
public:
  RibManagerFixture()
  {
    face = ndn::util::makeDummyClientFace(g_io);

    manager = make_shared<RibManager>(*face, keyChain);
    manager->registerWithNfd();

    advanceClocks(time::milliseconds(1));
    face->sentInterests.clear();
  }

  ~RibManagerFixture()
  {
    manager.reset();
    face.reset();
  }

  void
  extractParameters(Interest& interest, Name::Component& verb,
                    ControlParameters& extractedParameters)
  {
    const Name& name = interest.getName();
    verb = name[COMMAND_PREFIX.size()];
    const Name::Component& parameterComponent = name[COMMAND_PREFIX.size() + 1];

    Block rawParameters = parameterComponent.blockFromValue();
    extractedParameters.wireDecode(rawParameters);
  }

  void
  receiveCommandInterest(const Name& name, ControlParameters& parameters,
                         uint64_t incomingFaceId = DEFAULT_INCOMING_FACE_ID)
  {
    Name commandName = name;
    commandName.append(parameters.wireEncode());

    Interest commandInterest(commandName);
    commandInterest.setTag(make_shared<lp::IncomingFaceIdTag>(incomingFaceId));

    manager->m_managedRib.m_onSendBatchFromQueue = bind(&RibManagerFixture::onSendBatchFromQueue,
                                                        this, _1, parameters);

    face->receive(commandInterest);
    advanceClocks(time::milliseconds(1));
  }

  void
  onSendBatchFromQueue(const RibUpdateBatch& batch, const ControlParameters parameters)
  {
    BOOST_REQUIRE(batch.begin() != batch.end());
    RibUpdate update = *(batch.begin());

    Rib::UpdateSuccessCallback managerCallback =
      bind(&RibManager::onRibUpdateSuccess, manager, update);

    Rib& rib = manager->m_managedRib;

    // Simulate a successful response from NFD
    FibUpdater& updater = manager->m_fibUpdater;
    rib.onFibUpdateSuccess(batch, updater.m_inheritedRoutes, managerCallback);
  }


public:
  shared_ptr<RibManager> manager;
  shared_ptr<ndn::util::DummyClientFace> face;
  ndn::KeyChain keyChain;

  static const uint64_t DEFAULT_INCOMING_FACE_ID;

  static const Name COMMAND_PREFIX;
  static const name::Component ADD_NEXTHOP_VERB;
  static const name::Component REMOVE_NEXTHOP_VERB;

  static const Name REGISTER_COMMAND;
  static const Name UNREGISTER_COMMAND;
};

const uint64_t RibManagerFixture::DEFAULT_INCOMING_FACE_ID = 25122;
const Name RibManagerFixture::COMMAND_PREFIX("/localhost/nfd/rib");
const name::Component RibManagerFixture::ADD_NEXTHOP_VERB("add-nexthop");
const name::Component RibManagerFixture::REMOVE_NEXTHOP_VERB("remove-nexthop");
const Name RibManagerFixture::REGISTER_COMMAND("/localhost/nfd/rib/register");
const Name RibManagerFixture::UNREGISTER_COMMAND("/localhost/nfd/rib/unregister");

class AuthorizedRibManager : public RibManagerFixture
{
public:
  AuthorizedRibManager()
  {
    ConfigFile config;
    manager->setConfigFile(config);

    const std::string CONFIG_STRING =
    "rib\n"
    "{\n"
    "  localhost_security\n"
    "  {\n"
    "    trust-anchor\n"
    "    {\n"
    "      type any\n"
    "    }\n"
    "  }"
    "}";

    config.parse(CONFIG_STRING, true, "test-rib");
  }
};

typedef RibManagerFixture UnauthorizedRibManager;

BOOST_FIXTURE_TEST_SUITE(TestRibManager, RibManagerFixture)

BOOST_FIXTURE_TEST_CASE(ShortName, AuthorizedRibManager)
{
  Name commandName("/localhost/nfd/rib");
  ndn::nfd::ControlParameters parameters;

  receiveCommandInterest(commandName, parameters);
  // TODO verify error response
}

BOOST_FIXTURE_TEST_CASE(Basic, AuthorizedRibManager)
{
  ControlParameters parameters;
  parameters
    .setName("/hello")
    .setFaceId(1)
    .setCost(10)
    .setFlags(0)
    .setOrigin(128)
    .setExpirationPeriod(ndn::time::milliseconds::max());

  receiveCommandInterest(REGISTER_COMMAND, parameters);

  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
}

BOOST_FIXTURE_TEST_CASE(Register, AuthorizedRibManager)
{
  ControlParameters parameters;
  parameters
    .setName("/hello")
    .setFaceId(1)
    .setCost(10)
    .setFlags(0)
    .setOrigin(128)
    .setExpirationPeriod(ndn::time::milliseconds::max());

  receiveCommandInterest(REGISTER_COMMAND, parameters);

  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);

  Interest& request = face->sentInterests[0];

  ControlParameters extractedParameters;
  Name::Component verb;
  extractParameters(request, verb, extractedParameters);

  BOOST_CHECK_EQUAL(verb, ADD_NEXTHOP_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), parameters.getName());
  BOOST_CHECK_EQUAL(extractedParameters.getFaceId(), parameters.getFaceId());
  BOOST_CHECK_EQUAL(extractedParameters.getCost(), parameters.getCost());
}

BOOST_FIXTURE_TEST_CASE(Unregister, AuthorizedRibManager)
{
  ControlParameters addParameters;
  addParameters
    .setName("/hello")
    .setFaceId(1)
    .setCost(10)
    .setFlags(0)
    .setOrigin(128)
    .setExpirationPeriod(ndn::time::milliseconds::max());

  receiveCommandInterest(REGISTER_COMMAND, addParameters);
  face->sentInterests.clear();

  ControlParameters removeParameters;
  removeParameters
    .setName("/hello")
    .setFaceId(1)
    .setOrigin(128);

  receiveCommandInterest(UNREGISTER_COMMAND, removeParameters);

  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);

  Interest& request = face->sentInterests[0];

  ControlParameters extractedParameters;
  Name::Component verb;
  extractParameters(request, verb, extractedParameters);

  BOOST_CHECK_EQUAL(verb, REMOVE_NEXTHOP_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), removeParameters.getName());
  BOOST_CHECK_EQUAL(extractedParameters.getFaceId(), removeParameters.getFaceId());
}

BOOST_FIXTURE_TEST_CASE(SelfRegister, AuthorizedRibManager)
{
  ControlParameters parameters;
  parameters
    .setName("/hello");

  receiveCommandInterest(REGISTER_COMMAND, parameters, 10129);

  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);

  Interest& request = face->sentInterests[0];

  ControlParameters extractedParameters;
  Name::Component verb;
  extractParameters(request, verb, extractedParameters);

  BOOST_CHECK_EQUAL(verb, ADD_NEXTHOP_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), parameters.getName());
  BOOST_CHECK_EQUAL(extractedParameters.getFaceId(), 10129);
}

BOOST_FIXTURE_TEST_CASE(SelfUnregister, AuthorizedRibManager)
{
  ControlParameters addParameters;
  addParameters
    .setName("/hello")
    .setFaceId(10129);

  receiveCommandInterest(REGISTER_COMMAND, addParameters);
  face->sentInterests.clear();

  ControlParameters removeParameters;
  removeParameters
    .setName("/hello");

  receiveCommandInterest(UNREGISTER_COMMAND, removeParameters, 10129);

  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);

  Interest& request = face->sentInterests[0];

  ControlParameters extractedParameters;
  Name::Component verb;
  extractParameters(request, verb, extractedParameters);

  BOOST_CHECK_EQUAL(verb, REMOVE_NEXTHOP_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), removeParameters.getName());
  BOOST_CHECK_EQUAL(extractedParameters.getFaceId(), 10129);
}

BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand, UnauthorizedRibManager)
{
  ControlParameters parameters;
  parameters
    .setName("/hello")
    .setFaceId(1)
    .setCost(10)
    .setFlags(0)
    .setOrigin(128)
    .setExpirationPeriod(ndn::time::milliseconds::max());

  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 0);

  receiveCommandInterest(REGISTER_COMMAND, parameters);

  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 0);
}

BOOST_FIXTURE_TEST_CASE(RibStatusRequest, AuthorizedRibManager)
{
  Name prefix("/");

  Route route;
  route.faceId = 1;
  route.origin = 128;
  route.cost = 32;
  route.flags = ndn::nfd::ROUTE_FLAG_CAPTURE;

  manager->m_managedRib.insert(prefix, route);

  face->receive(Interest("/localhost/nfd/rib/list"));
  advanceClocks(time::milliseconds(1));

  BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
  RibStatusPublisherFixture::decodeRibEntryBlock(face->sentDatas[0], prefix, route);
}

BOOST_FIXTURE_TEST_CASE(CancelExpirationEvent, AuthorizedRibManager)
{
  // Register route
  ControlParameters addParameters;
  addParameters
    .setName("/expire")
    .setFaceId(1)
    .setCost(10)
    .setFlags(0)
    .setOrigin(128)
    .setExpirationPeriod(ndn::time::milliseconds(500));

  receiveCommandInterest(REGISTER_COMMAND, addParameters);
  face->sentInterests.clear();

  // Unregister route
  ControlParameters removeParameters;
  removeParameters
    .setName("/expire")
    .setFaceId(1)
    .setOrigin(128);

  receiveCommandInterest(UNREGISTER_COMMAND, removeParameters);

  // Reregister route
  addParameters.setExpirationPeriod(ndn::time::milliseconds::max());
  receiveCommandInterest(REGISTER_COMMAND, addParameters);

  advanceClocks(time::milliseconds(100), time::seconds(1));

  BOOST_REQUIRE_EQUAL(manager->m_managedRib.size(), 1);
}

BOOST_FIXTURE_TEST_CASE(RemoveInvalidFaces, AuthorizedRibManager)
{
  // Register valid face
  ControlParameters validParameters;
  validParameters
    .setName("/test")
    .setFaceId(1);

  receiveCommandInterest(REGISTER_COMMAND, validParameters);

  // Register invalid face
  ControlParameters invalidParameters;
  invalidParameters
    .setName("/test")
    .setFaceId(2);

  receiveCommandInterest(REGISTER_COMMAND, invalidParameters);

  BOOST_REQUIRE_EQUAL(manager->m_managedRib.size(), 2);

  // Receive status with only faceId: 1
  ndn::nfd::FaceStatus status;
  status.setFaceId(1);

  shared_ptr<Data> data = nfd::tests::makeData("/localhost/nfd/faces/list");
  data->setContent(status.wireEncode());

  shared_ptr<ndn::OBufferStream> buffer = make_shared<ndn::OBufferStream>();
  buffer->write(reinterpret_cast<const char*>(data->getContent().value()),
                data->getContent().value_size());

  manager->removeInvalidFaces(buffer);

  // Run scheduler
  advanceClocks(time::milliseconds(100), time::seconds(1));

  BOOST_REQUIRE_EQUAL(manager->m_managedRib.size(), 1);

  Rib::const_iterator it = manager->m_managedRib.find("/test");
  BOOST_REQUIRE(it != manager->m_managedRib.end());

  shared_ptr<RibEntry> entry = it->second;
  BOOST_CHECK_EQUAL(entry->hasFaceId(1), true);
  BOOST_CHECK_EQUAL(entry->hasFaceId(2), false);
}

BOOST_FIXTURE_TEST_CASE(LocalHopInherit, AuthorizedRibManager)
{
  using nfd::rib::RibManager;

  // Simulate NFD response
  ControlParameters result;
  result.setFaceId(261);

  manager->onNrdCommandPrefixAddNextHopSuccess(RibManager::REMOTE_COMMAND_PREFIX, result);

  // Register route that localhop prefix should inherit
  ControlParameters parameters;
  parameters
    .setName("/localhop/nfd")
    .setFaceId(262)
    .setCost(25)
    .setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT);

  Name commandName("/localhost/nfd/rib/register");

  receiveCommandInterest(commandName, parameters);

  // REMOTE_COMMAND_PREFIX should have its original route and the inherited route
  auto it = manager->m_managedRib.find(RibManager::REMOTE_COMMAND_PREFIX);

  BOOST_REQUIRE(it != manager->m_managedRib.end());
  const RibEntry::RouteList& inheritedRoutes = (*(it->second)).getInheritedRoutes();

  BOOST_CHECK_EQUAL(inheritedRoutes.size(), 1);
  auto routeIt = inheritedRoutes.begin();

  BOOST_CHECK_EQUAL(routeIt->faceId, 262);
  BOOST_CHECK_EQUAL(routeIt->cost, 25);
}

BOOST_FIXTURE_TEST_CASE(RouteExpiration, AuthorizedRibManager)
{
  // Register route
  ControlParameters parameters;
  parameters.setName("/expire")
            .setExpirationPeriod(ndn::time::milliseconds(500));

  receiveCommandInterest(REGISTER_COMMAND, parameters);
  face->sentInterests.clear();

  BOOST_REQUIRE_EQUAL(manager->m_managedRib.size(), 1);

  // Route should expire
  advanceClocks(time::milliseconds(100), time::seconds(1));

  BOOST_CHECK_EQUAL(manager->m_managedRib.size(), 0);
}

BOOST_FIXTURE_TEST_CASE(FaceDestroyEvent, AuthorizedRibManager)
{
  uint64_t faceToDestroy = 128;

  // Register valid face
  ControlParameters parameters;
  parameters.setName("/test")
            .setFaceId(faceToDestroy);

  receiveCommandInterest(REGISTER_COMMAND, parameters);
  BOOST_REQUIRE_EQUAL(manager->m_managedRib.size(), 1);

  // Don't respond with a success message from the FIB
  manager->m_managedRib.m_onSendBatchFromQueue = nullptr;

  manager->onFaceDestroyedEvent(faceToDestroy);
  BOOST_REQUIRE_EQUAL(manager->m_managedRib.size(), 0);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace rib
} // namespace nfd
