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

#include "tests/limited-io.hpp"
#include "tests/identity-management-fixture.hpp"
#include <ndn-cxx/util/dummy-client-face.hpp>

namespace nfd {
namespace rib {
namespace tests {

class RemoteRegistratorFixture : public nfd::tests::IdentityManagementFixture
{
public:
  RemoteRegistratorFixture()
    : face(ndn::util::makeDummyClientFace())
    , controller(make_shared<ndn::nfd::Controller>(std::ref(*face), m_keyChain))
    , remoteRegistrator(make_shared<RemoteRegistrator>(std::ref(*controller),
                                                       m_keyChain,
                                                       rib))
    , COMMAND_PREFIX("/localhop/nfd/rib")
    , REGISTER_VERB("register")
    , UNREGISTER_VERB("unregister")
  {
    readConfig();

    registerCallback();

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

  void
  readConfig()
  {
    ConfigFile config;
    config.addSectionHandler("remote_register",
                             bind(&RemoteRegistrator::loadConfig, remoteRegistrator, _1));

    const std::string CONFIG_STRING =
    "remote_register\n"
    "{\n"
    "  cost 15\n"
    "  timeout 10000\n"
    "  retry 2\n"
    "  refresh_interval 5\n"
    "}";

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

  void
  registerCallback()
  {
    rib.afterInsertEntry += [this] (const Name& prefix) {
      remoteRegistrator->registerPrefix(prefix);
    };

    rib.afterEraseEntry += [this] (const Name& prefix) {
      remoteRegistrator->unregisterPrefix(prefix);
    };
  }

  void
  insertEntryWithIdentity(Name identity,
                          name::Component appName = DEFAULT_APP_NAME,
                          uint64_t faceId = 0)
  {
    BOOST_CHECK_EQUAL(addIdentity(identity), true);

    FaceEntry faceEntry;
    faceEntry.faceId = faceId;

    rib.insert(identity.append(appName), faceEntry);

    face->processEvents(time::milliseconds(1));
  }

  void
  insertEntryWithoutIdentity(Name identity,
                             name::Component appName = DEFAULT_APP_NAME,
                             uint64_t faceId = 0)
  {
    FaceEntry faceEntry;
    faceEntry.faceId = faceId;

    rib.insert(identity.append(appName), faceEntry);

    face->processEvents(time::milliseconds(1));
  }

  void
  eraseEntryWithIdentity(Name identity,
                         name::Component appName = DEFAULT_APP_NAME,
                         uint64_t faceId = 0)
  {
    BOOST_CHECK_EQUAL(addIdentity(identity), true);

    FaceEntry faceEntry;
    faceEntry.faceId = faceId;

    rib.erase(identity.append(appName), faceEntry);

    face->processEvents(time::milliseconds(1));
  }

  void
  eraseEntryWithoutIdentity(Name identity,
                            name::Component appName = DEFAULT_APP_NAME,
                            uint64_t faceId = 0)
  {
    FaceEntry faceEntry;
    faceEntry.faceId = faceId;

    rib.erase(identity.append(appName), faceEntry);

    face->processEvents(time::milliseconds(1));
  }

  void
  eraseFace(uint64_t faceId)
  {
    rib.erase(faceId);

    face->processEvents(time::milliseconds(1));
  }

  void
  connectToHub()
  {
    rib.insert(Name("/localhop/nfd"), FaceEntry());

    face->processEvents(time::milliseconds(1));
  }

  void
  disconnectToHub()
  {
    rib.erase(Name("/localhop/nfd"), FaceEntry());

    face->processEvents(time::milliseconds(1));
  }

  void
  extractParameters(Interest& interest, Name::Component& verb,
                    ndn::nfd::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);
  }

public:
  Rib rib;
  shared_ptr<ndn::util::DummyClientFace> face;
  shared_ptr<ndn::nfd::Controller> controller;
  shared_ptr<RemoteRegistrator> remoteRegistrator;

  const Name COMMAND_PREFIX;
  const name::Component REGISTER_VERB;
  const name::Component UNREGISTER_VERB;

  static const name::Component DEFAULT_APP_NAME;
};

const name::Component RemoteRegistratorFixture::DEFAULT_APP_NAME("app");

BOOST_FIXTURE_TEST_SUITE(RemoteRegistrator, RemoteRegistratorFixture)

BOOST_FIXTURE_TEST_CASE(AutoTest, RemoteRegistratorFixture)
{
  BOOST_REQUIRE_EQUAL(1, 1);
}

BOOST_FIXTURE_TEST_CASE(RegisterWithoutConnection, RemoteRegistratorFixture)
{
  insertEntryWithIdentity("/remote/register");

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

BOOST_FIXTURE_TEST_CASE(RegisterWithoutIdentity, RemoteRegistratorFixture)
{
  connectToHub();

  insertEntryWithoutIdentity("/remote/register");

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

BOOST_FIXTURE_TEST_CASE(RegisterWithHubPrefix, RemoteRegistratorFixture)
{
  connectToHub();

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

BOOST_FIXTURE_TEST_CASE(RegisterWithLocalPrefix, RemoteRegistratorFixture)
{
  connectToHub();

  insertEntryWithIdentity("/localhost/prefix");

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

BOOST_FIXTURE_TEST_CASE(RegisterBasic, RemoteRegistratorFixture)
{
  connectToHub();

  Name identity("/remote/register");
  insertEntryWithIdentity(identity);

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

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

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

  BOOST_CHECK_EQUAL(verb, REGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), identity);
}

BOOST_FIXTURE_TEST_CASE(RegisterAdvanced, RemoteRegistratorFixture)
{
  connectToHub();

  Name identity("/remote/register");
  Name identityAddRib("/remote/register/rib");
  insertEntryWithIdentity(identityAddRib);

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

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

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

  BOOST_CHECK_EQUAL(verb, REGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), identity);
}

BOOST_FIXTURE_TEST_CASE(UnregisterWithoutInsert, RemoteRegistratorFixture)
{
  connectToHub();

  eraseEntryWithIdentity("/remote/register");

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

BOOST_FIXTURE_TEST_CASE(UnregisterWithoutConnection, RemoteRegistratorFixture)
{
  connectToHub();

  disconnectToHub();

  Name indentity("/remote/register");
  remoteRegistrator->m_regEntries.insert(
            nfd::rib::RemoteRegistrator::RegisteredEntry(indentity, EventId()));

  eraseEntryWithIdentity(indentity);

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

BOOST_FIXTURE_TEST_CASE(UnregisterWithoutSuccessfullRegistration,
                        RemoteRegistratorFixture)
{
  connectToHub();

  Name identity("/remote/register");

  insertEntryWithIdentity(identity);

  eraseEntryWithIdentity(identity);

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

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

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

  BOOST_CHECK_EQUAL(verb, REGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), identity);
}

BOOST_FIXTURE_TEST_CASE(UnregisterBasic, RemoteRegistratorFixture)
{
  connectToHub();

  Name identity("/remote/register");

  insertEntryWithIdentity(identity);

  EventId event;

  remoteRegistrator->m_regEntries.insert(
          nfd::rib::RemoteRegistrator::RegisteredEntry(identity, event));

  eraseEntryWithIdentity(identity);

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

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

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

  BOOST_CHECK_EQUAL(verb, UNREGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), identity);
}

BOOST_FIXTURE_TEST_CASE(UnregisterAdvanced, RemoteRegistratorFixture)
{
  connectToHub();

  Name identityShort("/remote/register");
  Name identityLong("/remote/register/long");

  EventId eventShort;
  EventId eventLong;

  insertEntryWithIdentity(identityShort, name::Component("appA"));

  remoteRegistrator->m_regEntries.insert(
          nfd::rib::RemoteRegistrator::RegisteredEntry(identityShort,
                                                       eventShort));

  insertEntryWithIdentity(identityShort, name::Component("appB"));

  insertEntryWithIdentity(identityLong);

  remoteRegistrator->m_regEntries.insert(
          nfd::rib::RemoteRegistrator::RegisteredEntry(identityLong,
                                                       eventLong));

  // two registration commands are generated for identityShort and identityLong
  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 2);

  eraseEntryWithIdentity(identityShort, name::Component("appA"));

  // no unregistration command is generated as appB also exists
  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 2);

  eraseEntryWithIdentity(identityShort, name::Component("appB"));

  // one unregistration command is generated for identityShort
  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 3);

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

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

  BOOST_CHECK_EQUAL(verb, UNREGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), identityShort);
}

BOOST_FIXTURE_TEST_CASE(EraseFace, RemoteRegistratorFixture)
{
  connectToHub();

  Name identity("/remote/register");
  uint64_t faceId = 517;

  insertEntryWithIdentity(identity, DEFAULT_APP_NAME, faceId);

  EventId event;

  remoteRegistrator->m_regEntries.insert(
          nfd::rib::RemoteRegistrator::RegisteredEntry(identity, event));

  eraseFace(faceId);

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

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

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

  BOOST_CHECK_EQUAL(verb, UNREGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParameters.getName(), identity);
}

BOOST_FIXTURE_TEST_CASE(RebuildConnection, RemoteRegistratorFixture)
{
  connectToHub();

  Name identity("/remote/register");

  insertEntryWithIdentity(identity);

  EventId event;

  remoteRegistrator->m_regEntries.insert(
          nfd::rib::RemoteRegistrator::RegisteredEntry(identity, event));

  disconnectToHub();

  connectToHub();

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

  Interest& request1 = face->sentInterests[0];
  Interest& request2 = face->sentInterests[1];

  ndn::nfd::ControlParameters extractedParameters1, extractedParameters2;
  Name::Component verb1, verb2;
  extractParameters(request1, verb1, extractedParameters1);
  extractParameters(request2, verb2, extractedParameters2);

  BOOST_CHECK_EQUAL(verb1, REGISTER_VERB);
  BOOST_CHECK_EQUAL(verb2, REGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParameters1.getName(),
                    extractedParameters2.getName());
}

BOOST_AUTO_TEST_SUITE_END()

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