/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2011-2015  Regents of the University of California.
 *
 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
 * contributors.
 *
 * ndnSIM 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.
 *
 * ndnSIM 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
 * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "helper/ndn-scenario-helper.hpp"
#include "helper/ndn-app-helper.hpp"

#include <ndn-cxx/face.hpp>

#include "../tests-common.hpp"

namespace ns3 {
namespace ndn {

BOOST_FIXTURE_TEST_SUITE(ModelNdnL3Protocol, ScenarioHelperWithCleanupFixture)

class TesterApp
{
public:
  TesterApp(const std::function<void(::ndn::Face& face)>& func)
  {
    func(m_face);
  }

protected:
  ::ndn::Face m_face;
};

class ManagerCheckFixture : public ScenarioHelperWithCleanupFixture
{
public:
  void
  setupAndRun()
  {
    createTopology({
        {"1"},
          });

    requestedDatasets = {
      "/localhost/nfd/rib/list",
      "/localhost/nfd/faces/list",
      "/localhost/nfd/strategy-choice/list",
      "/localhost/nfd/status"
    };

    FactoryCallbackApp::Install(getNode("1"), [this] () -> shared_ptr<void> {
        return make_shared<TesterApp>([this] (::ndn::Face& face) {
            for (const Name& dataset : requestedDatasets) {
              face.expressInterest(dataset, [&] (const Interest& i, Data& data) {
                  BOOST_TEST_MESSAGE(data.getName());
                  receivedDatasets.insert(data.getName().getPrefix(-2));
                },
                std::bind([]{}));
            }
          });
      })
      .Start(Seconds(0.01));

    Simulator::Stop(Seconds(1.0));
    Simulator::Run();
  }

public:
  std::set<Name> requestedDatasets;
  std::set<Name> receivedDatasets;
};

BOOST_FIXTURE_TEST_SUITE(ManagerCheck, ManagerCheckFixture)

BOOST_AUTO_TEST_CASE(AllEnabled)
{
  setupAndRun();

  BOOST_CHECK_EQUAL(requestedDatasets.size(), receivedDatasets.size());
  BOOST_CHECK_EQUAL_COLLECTIONS(requestedDatasets.begin(), requestedDatasets.end(),
                                receivedDatasets.begin(), receivedDatasets.end());
}

BOOST_AUTO_TEST_CASE(DisabledRibManager)
{
  // Disable RIB manager
  disableRibManager();

  setupAndRun();

  BOOST_CHECK_EQUAL(requestedDatasets.size(), receivedDatasets.size() + 1);

  requestedDatasets.erase("/localhost/nfd/rib/list");
  BOOST_CHECK_EQUAL_COLLECTIONS(requestedDatasets.begin(), requestedDatasets.end(),
                                receivedDatasets.begin(), receivedDatasets.end());
}

BOOST_AUTO_TEST_CASE(DisabledFaceManager)
{
  // Disable Face manager
  disableFaceManager();

  setupAndRun();

  BOOST_CHECK_EQUAL(requestedDatasets.size(), receivedDatasets.size() + 1);

  requestedDatasets.erase("/localhost/nfd/faces/list");
  BOOST_CHECK_EQUAL_COLLECTIONS(requestedDatasets.begin(), requestedDatasets.end(),
                                receivedDatasets.begin(), receivedDatasets.end());
}

BOOST_AUTO_TEST_CASE(DisabledStrategyChoiceManager)
{
  // Disable Strategy Choice Manager manager
  disableStrategyChoiceManager();

  setupAndRun();

  BOOST_CHECK_EQUAL(requestedDatasets.size(), receivedDatasets.size() + 1);

  requestedDatasets.erase("/localhost/nfd/strategy-choice/list");
  BOOST_CHECK_EQUAL_COLLECTIONS(requestedDatasets.begin(), requestedDatasets.end(),
                                receivedDatasets.begin(), receivedDatasets.end());
}

BOOST_AUTO_TEST_CASE(DisabledStatusServer)
{
  // Disable Status Server manager
  disableStatusServer();

  setupAndRun();

  BOOST_CHECK_EQUAL(requestedDatasets.size(), receivedDatasets.size() + 1);

  requestedDatasets.erase("/localhost/nfd/status");
  BOOST_CHECK_EQUAL_COLLECTIONS(requestedDatasets.begin(), requestedDatasets.end(),
                                receivedDatasets.begin(), receivedDatasets.end());
}

BOOST_AUTO_TEST_SUITE_END() // ManagerCheck

BOOST_AUTO_TEST_SUITE_END() // ModelNdnL3Protocol

} // namespace ndn
} // namespace ns3
