/* -*- 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 nfd::tests::UnitTestTimeFixture
{
public:
  RemoteRegistratorFixture()
    : face(ndn::util::makeDummyClientFace(getGlobalIoService()))
    , 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();

    remoteRegistrator->enable();

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

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


    if (isSetRetry)
      {
        const std::string CONFIG_STRING =
        "remote_register\n"
        "{\n"
        "  cost 15\n"
        "  timeout 1000\n"
        "  retry 1\n"
        "  refresh_interval 5\n"
        "}";

        config.parse(CONFIG_STRING, true, "test-remote-register");
      }
    else
      {
        const std::string CONFIG_STRING =
        "remote_register\n"
        "{\n"
        "  cost 15\n"
        "  timeout 100000\n"
        "  retry 0\n"
        "  refresh_interval 5\n"
        "}";

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

  void
  waitForTimeout()
  {
    advanceClocks(time::milliseconds(100), time::seconds(1));
  }

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

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

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

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

    advanceClocks(time::milliseconds(1));
  }

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

    advanceClocks(time::milliseconds(1));
  }

  void
  connectToHub()
  {
    rib.insert(COMMAND_PREFIX, FaceEntry());

    advanceClocks(time::milliseconds(1));
  }

  void
  disconnectToHub()
  {
    rib.erase(COMMAND_PREFIX, FaceEntry());

    advanceClocks(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(RegisterWithRedundantCallback, RemoteRegistratorFixture)
{
  remoteRegistrator->enable();

  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(RegisterRetry, RemoteRegistratorFixture)
{
  // setRetry
  readConfig(true);

  connectToHub();

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

  waitForTimeout();

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

  Interest& requestFirst  = face->sentInterests[0];
  Interest& requestSecond = face->sentInterests[1];

  ndn::nfd::ControlParameters extractedParametersFirst, extractedParametersSecond;
  Name::Component verbFirst, verbSecond;
  extractParameters(requestFirst,  verbFirst,  extractedParametersFirst);
  extractParameters(requestSecond, verbSecond, extractedParametersSecond);

  BOOST_CHECK_EQUAL(verbFirst,  REGISTER_VERB);
  BOOST_CHECK_EQUAL(verbSecond, REGISTER_VERB);
  BOOST_CHECK_EQUAL(extractedParametersFirst.getName(),  identity);
  BOOST_CHECK_EQUAL(extractedParametersSecond.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
