/* -*- 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 "publisher/lsdb-dataset-interest-handler.hpp"
#include "tlv/tlv-nlsr.hpp"

#include "publisher-fixture.hpp"
#include "../boost-test.hpp"

#include <ndn-cxx/mgmt/nfd/control-response.hpp>

namespace nlsr {
namespace test {

void
processDatasetInterest(std::shared_ptr<ndn::util::DummyClientFace> face,
                       std::function<bool(const ndn::Block&)> isSameType)
{
  face->processEvents(ndn::time::milliseconds(1));

  BOOST_REQUIRE_EQUAL(face->sentData.size(), 1);
  ndn::Block parser(face->sentData[0].getContent());
  parser.parse();

  ndn::Block::element_const_iterator it = parser.elements_begin();
  BOOST_CHECK_EQUAL(isSameType(*it), true);
  ++it;

  BOOST_CHECK(it == parser.elements_end());

  face->sentData.clear();
}

void
checkErrorResponse(std::shared_ptr<ndn::util::DummyClientFace> face, uint64_t expectedCode)
{
  BOOST_REQUIRE_EQUAL(face->sentData.size(), 1);

  ndn::nfd::ControlResponse response(face->sentData[0].getContent().blockFromValue());
  BOOST_CHECK_EQUAL(response.getCode(), expectedCode);

  face->sentData.clear();
}

BOOST_FIXTURE_TEST_SUITE(PublisherTestLsdbDatasetInterestHandler, PublisherFixture)

BOOST_AUTO_TEST_CASE(Basic)
{
  // Install adjacency LSA
  AdjLsa adjLsa;
  adjLsa.setOrigRouter("/RouterA");
  addAdjacency(adjLsa, "/RouterA/adjacency1", "udp://face-1", 10);
  lsdb.installAdjLsa(adjLsa);

  // Install coordinate LSA
  CoordinateLsa coordinateLsa = createCoordinateLsa("/RouterA", 10.0, 20.0);
  lsdb.installCoordinateLsa(coordinateLsa);

  // Install Name LSA
  NameLsa nameLsa;
  nameLsa.setOrigRouter("/RouterA");
  nameLsa.addName("/RouterA/name1");
  lsdb.installNameLsa(nameLsa);

  ndn::Name thisRouter("/This/Router");
  LsdbDatasetInterestHandler publisher(lsdb, *face, keyChain);
  publisher.setRouterNameCommandPrefix(thisRouter);

  publisher.startListeningOnLocalhost();

  face->processEvents(ndn::time::milliseconds(10));

  // Localhost prefix
  ndn::Name localhostCommandPrefix = publisher.getLocalhostCommandPrefix();

  // Request adjacency LSAs
  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("adjacencies")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });

  // Request coordinate LSAs
  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("coordinates")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });

  // Request Name LSAs
  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("names")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });

  // Request LSDB Status
  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("list")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::LsdbStatus; });

  // Router name prefix
  ndn::Name routerCommandPrefix = publisher.getLocalhostCommandPrefix();

  // Request adjacency LSAs
  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("adjacencies")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });

  // Request coordinate LSAs
  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("coordinates")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });

  // Request Name LSAs
  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("names")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });

  // Request LSDB Status
  face->receive(ndn::Interest(ndn::Name(routerCommandPrefix).append("list")));
  processDatasetInterest(face,
    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::LsdbStatus; });
}

BOOST_AUTO_TEST_CASE(InvalidCommand)
{
  ndn::Name thisRouter("/This/Router");
  LsdbDatasetInterestHandler publisher(lsdb, *face, keyChain);
  publisher.setRouterNameCommandPrefix(thisRouter);

  // Localhost prefix
  publisher.startListeningOnLocalhost();
  face->processEvents(ndn::time::milliseconds(10));

  ndn::Name localhostCommandPrefix = publisher.getLocalhostCommandPrefix();

  // Unsupported command
  face->receive(ndn::Interest(ndn::Name(localhostCommandPrefix).append("unsupported")));
  face->processEvents(ndn::time::milliseconds(1));

  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_UNSUPPORTED_COMMAND);

  // Long malformed command
  face->receive(
    ndn::Interest(ndn::Name(localhostCommandPrefix).append("extra").append("malformed")));
  face->processEvents(ndn::time::milliseconds(1));

  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_MALFORMED_COMMAND);

  // Router name prefix
  publisher.startListeningOnRouterPrefix();
  face->processEvents(ndn::time::milliseconds(10));

  ndn::Name remoteCommandPrefix = publisher.getRouterNameCommandPrefix();

  // Unsupported command
  face->receive(ndn::Interest(ndn::Name(remoteCommandPrefix).append("unsupported")));
  face->processEvents(ndn::time::milliseconds(1));

  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_UNSUPPORTED_COMMAND);

  // Long malformed command
  face->receive(ndn::Interest(ndn::Name(remoteCommandPrefix).append("extra").append("malformed")));
  face->processEvents(ndn::time::milliseconds(1));

  checkErrorResponse(face, LsdbDatasetInterestHandler::ERROR_CODE_MALFORMED_COMMAND);

  // Short malformed command
  face->receive(ndn::Interest(ndn::Name(thisRouter).append("malformed")));
  face->processEvents(ndn::time::milliseconds(1));

  BOOST_CHECK_EQUAL(face->sentData.size(), 0);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace test
} // namespace nlsr
