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

#include "core/random.hpp"
#include "face/face.hpp"
#include "face/internal-face.hpp"
#include "fw/strategy.hpp"
#include "table/name-tree.hpp"
#include "table/strategy-choice.hpp"

#include "nfd-manager-common-fixture.hpp"
#include "tests/daemon/face/dummy-face.hpp"
#include "tests/daemon/fw/dummy-strategy.hpp"
#include "tests/daemon/fw/install-strategy.hpp"

#include <ndn-cxx/mgmt/nfd/strategy-choice.hpp>

namespace nfd {
namespace tests {

class StrategyChoiceManagerFixture : public NfdManagerCommonFixture
{
public:
  StrategyChoiceManagerFixture()
    : m_strategyChoice(m_forwarder.getStrategyChoice())
    , m_manager(m_strategyChoice, m_dispatcher, *m_authenticator)
  {
    setTopPrefix();
    setPrivilege("strategy-choice");
  }

public:
  void
  installStrategy(const Name& strategyName)
  {
    install<DummyStrategy>(m_forwarder, strategyName);
  }

  const Name&
  findStrategy(const Name& name)
  {
    return m_strategyChoice.findEffectiveStrategy(name).getName();
  }

  ControlParameters
  makeParameters(const Name& name, const Name& strategy)
  {
    return ControlParameters().setName(name).setStrategy(strategy);
  }

protected:
  StrategyChoice& m_strategyChoice;
  StrategyChoiceManager m_manager;
};

BOOST_AUTO_TEST_SUITE(Mgmt)
BOOST_FIXTURE_TEST_SUITE(TestStrategyChoiceManager, StrategyChoiceManagerFixture)

BOOST_AUTO_TEST_CASE(SetStrategy)
{
  auto testSetStrategy = [this] (const ControlParameters& parameters) -> Name {
    m_responses.clear();
    auto command = makeControlCommandRequest("/localhost/nfd/strategy-choice/set", parameters);
    receiveInterest(command);
    return command->getName();
  };

  installStrategy("/localhost/nfd/strategy/test-strategy-a");
  installStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%01"); // version 1
  installStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%02"); // version 2

  auto parametersA  = makeParameters("test", "/localhost/nfd/strategy/test-strategy-a");
  auto parametersB  = makeParameters("test", "/localhost/nfd/strategy/test-strategy-b");
  auto parametersC1 = makeParameters("test", "/localhost/nfd/strategy/test-strategy-c/%FD%01");
  auto parametersC  = makeParameters("test", "/localhost/nfd/strategy/test-strategy-c");

  auto commandNameA = testSetStrategy(parametersA); // succeed
  BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
  BOOST_CHECK_EQUAL(checkResponse(0, commandNameA, makeResponse(200, "OK", parametersA)),
                    CheckResponseResult::OK);
  BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-a");

  auto commandNameB = testSetStrategy(parametersB); // not installed
  BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
  BOOST_CHECK_EQUAL(checkResponse(0, commandNameB, ControlResponse(504, "Unsupported strategy")),
                    CheckResponseResult::OK);

  auto commandNameC1 = testSetStrategy(parametersC1); // specified version
  BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
  BOOST_CHECK_EQUAL(checkResponse(0, commandNameC1, makeResponse(200, "OK", parametersC1)),
                    CheckResponseResult::OK);
  BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-c/%FD%01");

  auto commandNameC = testSetStrategy(parametersC); // latest version
  parametersC.setStrategy("/localhost/nfd/strategy/test-strategy-c/%FD%02"); // change to latest
  BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
  BOOST_CHECK_EQUAL(checkResponse(0, commandNameC, makeResponse(200, "OK", parametersC)),
                    CheckResponseResult::OK);
  BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-c/%FD%02");
}

BOOST_AUTO_TEST_CASE(UnsetStrategy)
{
  auto testUnsetStrategy = [this] (const ControlParameters& parameters) -> Name {
    m_responses.clear();
    auto command = makeControlCommandRequest("/localhost/nfd/strategy-choice/unset", parameters);
    receiveInterest(command);
    return command->getName();
  };

  installStrategy("/localhost/nfd/strategy/test-strategy-a");
  installStrategy("/localhost/nfd/strategy/test-strategy-b");
  installStrategy("/localhost/nfd/strategy/test-strategy-c");

  BOOST_CHECK(m_strategyChoice.insert("ndn:/", "/localhost/nfd/strategy/test-strategy-a")); // root
  BOOST_CHECK(m_strategyChoice.insert("/test", "/localhost/nfd/strategy/test-strategy-b")); // test
  BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a");

  auto parametersRoot = ControlParameters().setName("ndn:/"); // root prefix
  auto parametersNone = ControlParameters().setName("/none"); // no such entry
  auto parametersTest = ControlParameters().setName("/test"); // has such entry

  BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a"); // root
  auto commandRootName = testUnsetStrategy(parametersRoot);
  auto expectedResponse = ControlResponse(400, "failed in validating parameters");
  BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
  BOOST_CHECK_EQUAL(checkResponse(0, commandRootName, expectedResponse), CheckResponseResult::OK);
  BOOST_CHECK_EQUAL(findStrategy("/"), "/localhost/nfd/strategy/test-strategy-a"); // keep as root

  BOOST_CHECK_EQUAL(findStrategy("/none"), "/localhost/nfd/strategy/test-strategy-a"); // root
  auto commandNoneName = testUnsetStrategy(parametersNone);
  BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
  BOOST_CHECK_EQUAL(checkResponse(0, commandNoneName, makeResponse(200, "OK", parametersNone)),
                    CheckResponseResult::OK);
  BOOST_CHECK_EQUAL(findStrategy("/none"), "/localhost/nfd/strategy/test-strategy-a"); // root

  BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-b"); // self
  auto commandTestName = testUnsetStrategy(parametersTest);
  BOOST_REQUIRE_EQUAL(m_responses.size(), 1);
  BOOST_CHECK_EQUAL(checkResponse(0, commandTestName, makeResponse(200, "OK", parametersTest)),
                    CheckResponseResult::OK);
  BOOST_CHECK_EQUAL(findStrategy("/test"), "/localhost/nfd/strategy/test-strategy-a"); // parent
}

// @todo Remove when ndn::nfd::StrategyChoice implements operator!= and operator<<
class StrategyChoice : public ndn::nfd::StrategyChoice
{
public:
  StrategyChoice() = default;

  StrategyChoice(const ndn::nfd::StrategyChoice& entry)
    : ndn::nfd::StrategyChoice(entry)
  {
  }
};

bool
operator!=(const StrategyChoice& left, const StrategyChoice& right)
{
  return left.getName() != right.getName() || left.getStrategy() != right.getStrategy();
}

std::ostream&
operator<<(std::ostream &os, const StrategyChoice& entry)
{
  os << "[ " << entry.getName() << ", " << entry.getStrategy() << " ]";
  return os;
}

BOOST_AUTO_TEST_CASE(StrategyChoiceDataset)
{
  size_t nPreInsertedStrategies = m_strategyChoice.size(); // the best-route strategy
  std::set<Name> actualNames, actualStrategies;
  for (const auto& entry : m_strategyChoice) {
    actualNames.insert(entry.getPrefix());
    actualStrategies.insert(entry.getStrategyName());
  }

  std::uniform_int_distribution<uint64_t> dist;
  size_t nEntries = 1024;
  for (size_t i = 0 ; i < nEntries ; i++) {
    auto name = Name("test-name").appendSegment(i);
    auto strategy = Name("test-strategy").appendSegment(dist(getGlobalRng()));
    auto entry = ndn::nfd::StrategyChoice().setName(name).setStrategy(strategy);
    actualNames.insert(name);
    actualStrategies.insert(strategy);
    installStrategy(strategy);
    m_strategyChoice.insert(name, strategy);
  }
  nEntries += nPreInsertedStrategies;

  receiveInterest(makeInterest("/localhost/nfd/strategy-choice/list"));

  Block content;
  BOOST_CHECK_NO_THROW(content = concatenateResponses());
  BOOST_CHECK_NO_THROW(content.parse());
  BOOST_CHECK_EQUAL(content.elements().size(), nEntries);

  std::vector<StrategyChoice> receivedRecords, expectedRecords;
  for (size_t idx = 0; idx < nEntries; ++idx) {
    BOOST_TEST_MESSAGE("processing element: " << idx);

    StrategyChoice decodedEntry;
    BOOST_REQUIRE_NO_THROW(decodedEntry.wireDecode(content.elements()[idx]));
    receivedRecords.push_back(decodedEntry);

    actualNames.erase(decodedEntry.getName());
    actualStrategies.erase(decodedEntry.getStrategy());

    auto result = m_strategyChoice.get(decodedEntry.getName());
    BOOST_REQUIRE(result.first);

    auto record = StrategyChoice().setName(decodedEntry.getName()).setStrategy(result.second);
    expectedRecords.push_back(record);
  }

  BOOST_CHECK_EQUAL(actualNames.size(), 0);
  BOOST_CHECK_EQUAL(actualStrategies.size(), 0);
  BOOST_CHECK_EQUAL_COLLECTIONS(receivedRecords.begin(), receivedRecords.end(),
                                expectedRecords.begin(), expectedRecords.end());
}

BOOST_AUTO_TEST_SUITE_END() // TestStrategyChoiceManager
BOOST_AUTO_TEST_SUITE_END() // Mgmt

} // namespace tests
} // namespace nfd
