/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2017,  The University of Memphis,
 *                           Regents of the University of California,
 *                           Arizona Board of Regents.
 *
 * This file is part of NLSR (Named-data Link State Routing).
 * See AUTHORS.md for complete list of NLSR authors and contributors.
 *
 * NLSR 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.
 *
 * NLSR 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
 * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "update/nfd-rib-command-processor.hpp"

#include "../test-common.hpp"
#include "../control-commands.hpp"
#include "conf-parameter.hpp"
#include "adjacency-list.hpp"
#include "nlsr.hpp"

#include <ndn-cxx/util/dummy-client-face.hpp>

#include <ndn-cxx/security/key-chain.hpp>

namespace nlsr {
namespace update {
namespace test {

class NfdRibCommandProcessorFixture : public nlsr::test::UnitTestTimeFixture
{
public:
  NfdRibCommandProcessorFixture()
    : face(g_ioService, keyChain, {true, true})
    , nlsr(g_ioService, g_scheduler, face, g_keyChain)
    , namePrefixes(nlsr.getNamePrefixList())
    , processor(nlsr.getNfdRibCommandProcessor())
  {
    // Set the network so the LSA prefix is constructed
    nlsr.getConfParameter().setNetwork("/ndn");

    // Initialize NLSR so a sync socket is created
    nlsr.initialize();
    this->advanceClocks(ndn::time::milliseconds(10), 1);
    face.sentInterests.clear();
  }

  std::shared_ptr<ndn::Interest>
  makeInterest(const ndn::Name& name, uint32_t nonce)
  {
    auto interest = std::make_shared<ndn::Interest>(name);
    if (nonce != 0) {
      interest->setNonce(nonce);
    }
    return interest;
  }

  bool
  wasRoutingUpdatePublished()
  {
    const ndn::Name& lsaPrefix = nlsr.getConfParameter().getLsaPrefix();

    const auto& it = std::find_if(face.sentData.begin(), face.sentData.end(),
      [lsaPrefix] (const ndn::Data& data) {
        return lsaPrefix.isPrefixOf(data.getName());
      });

    return (it != face.sentData.end());
  }

public:
  ndn::util::DummyClientFace face;
  ndn::KeyChain keyChain;

  Nlsr nlsr;
  NamePrefixList& namePrefixes;
  NfdRibCommandProcessor& processor;
};

typedef boost::mpl::vector<NfdRibRegisterCommand, NfdRibUnregisterCommand> Commands;

BOOST_FIXTURE_TEST_SUITE(TestNfdRibCommandProcessor, NfdRibCommandProcessorFixture)

BOOST_AUTO_TEST_CASE_TEMPLATE(ValidateParametersSuccess, NfdRibCommand, Commands)
{
  ndn::nfd::ControlParameters parameters;
  parameters.setName("/test/prefixA");

  BOOST_CHECK(processor.validateParameters<NfdRibCommand>(parameters));
}

BOOST_AUTO_TEST_CASE_TEMPLATE(ValidateParametersFailure, NfdRibCommand, Commands)
{
  ndn::nfd::ControlParameters parameters;
  parameters.setName("/test/prefixA").setCost(10);

  bool wasValidated = true;
  try {
    processor.validateParameters<NfdRibCommand>(parameters);
  }
  catch (...) {
    wasValidated = false;
  }
  BOOST_CHECK(!wasValidated);
}

BOOST_AUTO_TEST_CASE(InsertPrefix)
{
  ndn::nfd::ControlParameters parameters;
  ndn::Name prefixName("/test/prefixA");
  parameters.setName(prefixName);

  processor.insertPrefix(parameters);
  this->advanceClocks(ndn::time::milliseconds(10), 1);

  BOOST_CHECK_EQUAL(namePrefixes.getNameList().size(), 1);
  auto itr = std::find(namePrefixes.getNameList().begin(), namePrefixes.getNameList().end(),
                       prefixName);
  if (itr == namePrefixes.getNameList().end()) {
    BOOST_FAIL("Prefix was not inserted!");
  }
  BOOST_CHECK_EQUAL((*itr), parameters.getName());
  BOOST_CHECK(wasRoutingUpdatePublished());
}

BOOST_AUTO_TEST_CASE(RemovePrefix)
{
  ndn::Name prefixName("/test/prefixA");
  namePrefixes.getNameList().push_back(prefixName);
  ndn::nfd::ControlParameters parameters;
  parameters.setName("/test/prefixA");

  BOOST_CHECK_EQUAL(namePrefixes.getNameList().size(), 1);
  processor.removePrefix(parameters);
  this->advanceClocks(ndn::time::milliseconds(10), 1);

  BOOST_CHECK_EQUAL(namePrefixes.getNameList().size(), 0);
  auto itr = std::find(namePrefixes.getNameList().begin(), namePrefixes.getNameList().end(),
                       prefixName);
  if (itr != namePrefixes.getNameList().end()) {
    BOOST_FAIL("Prefix was not removed!");
  }
  BOOST_CHECK(wasRoutingUpdatePublished());
}

BOOST_AUTO_TEST_CASE(onReceiveInterestRegisterCommand)
{
  ndn::Name name("/localhost/nlsr/rib/register");
  ndn::Name prefixName("/test/prefixA");
  ndn::nfd::ControlParameters parameters;

  shared_ptr<ndn::Interest> command = makeInterest(name.append(parameters.setName(prefixName)
    .wireEncode()), 0);

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

  BOOST_CHECK_EQUAL(namePrefixes.getNameList().size(), 1);
  auto itr = std::find(namePrefixes.getNameList().begin(), namePrefixes.getNameList().end(),
                       prefixName);
  if (itr == namePrefixes.getNameList().end()) {
    BOOST_FAIL("Prefix was not inserted!");
  }
  BOOST_CHECK_EQUAL((*itr), prefixName);
  BOOST_CHECK(wasRoutingUpdatePublished());
}

BOOST_AUTO_TEST_CASE(onReceiveInterestUnregisterCommand)
{
  ndn::Name name("/localhost/nlsr/rib/unregister");
  ndn::Name prefixName("/test/prefixA");
  ndn::nfd::ControlParameters parameters;

  namePrefixes.getNameList().push_back(prefixName);

  shared_ptr<ndn::Interest> command = makeInterest(name.append(parameters.setName(prefixName)
    .wireEncode()), 0);

  face.receive(ndn::Interest(name));
  this->advanceClocks(ndn::time::milliseconds(10), 1);

  BOOST_CHECK_EQUAL(namePrefixes.getNameList().size(), 0);
  BOOST_CHECK(wasRoutingUpdatePublished());
}

BOOST_AUTO_TEST_CASE(onReceiveInterestInvalidPrefix)
{
  ndn::Name name("/localhost/invalid/rib/register");
  ndn::Name prefixName("/test/prefixA");
  ndn::nfd::ControlParameters parameters;

  shared_ptr<ndn::Interest> command = makeInterest(name.append(parameters.setName(prefixName)
    .wireEncode()), 0);

  face.receive(ndn::Interest(name));
  this->advanceClocks(ndn::time::milliseconds(10), 1);

  BOOST_CHECK_EQUAL(namePrefixes.getNameList().size(), 0);
  BOOST_CHECK(!wasRoutingUpdatePublished());
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace test
} // namespace update
} // namespace nlsr
