/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2023,  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 "lsdb.hpp"
#include "lsa/lsa.hpp"
#include "name-prefix-list.hpp"

#include "tests/io-key-chain-fixture.hpp"
#include "tests/test-common.hpp"

#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
#include <ndn-cxx/security/validator-null.hpp>
#include <ndn-cxx/util/segment-fetcher.hpp>

#include <unistd.h>

namespace nlsr {
namespace test {

class LsdbFixture : public IoKeyChainFixture
{
public:
  LsdbFixture()
    : face(m_io, m_keyChain, {true, true})
    , conf(face, m_keyChain)
    , confProcessor(conf)
    , lsdb(face, m_keyChain, conf)
  {
    m_keyChain.createIdentity("/ndn/site/%C1.Router/this-router");

    advanceClocks(10_ms);
    face.sentInterests.clear();
  }

  void
  areNamePrefixListsEqual(NamePrefixList& lhs, NamePrefixList& rhs)
  {
    auto lhsList = lhs.getNames();
    auto rhsList = rhs.getNames();
    BOOST_REQUIRE_EQUAL(lhsList.size(), rhsList.size());

    auto i = lhsList.begin();
    auto j = rhsList.begin();
    for (; i != lhsList.end(); ++i, ++j) {
      BOOST_CHECK_EQUAL(*i, *j);
    }
  }

  void
  isFirstNameLsaEqual(const Lsdb& otherLsdb)
  {
    auto selfLsaRange = lsdb.getLsdbIterator<NameLsa>();
    auto otherLsaRange = otherLsdb.getLsdbIterator<NameLsa>();

    if (selfLsaRange.first != selfLsaRange.second && otherLsaRange.first != otherLsaRange.second) {
      auto ownLsa = std::static_pointer_cast<NameLsa>(*selfLsaRange.first);
      auto otherLsa = std::static_pointer_cast<NameLsa>(*otherLsaRange.first);
      BOOST_CHECK_EQUAL(ownLsa->getNpl(), otherLsa->getNpl());
      return;
    }
    BOOST_CHECK(false);
  }

  void
  checkSignalResult(LsdbUpdate updateType,
                    const std::shared_ptr<Lsa>& lsaPtr,
                    const std::list<ndn::Name>& namesToAdd,
                    const std::list<ndn::Name>& namesToRemove)
  {
    BOOST_CHECK(updateHappened);
    BOOST_CHECK_EQUAL(lsaPtrCheck->getOriginRouter(), lsaPtr->getOriginRouter());
    BOOST_CHECK_EQUAL(lsaPtrCheck->getType(), lsaPtr->getType());
    BOOST_CHECK(updateType == updateTypeCheck);
    BOOST_CHECK(namesToAdd == namesToAddCheck);
    BOOST_CHECK(namesToRemove == namesToRemoveCheck);
    updateHappened = false;
  }

  void
  connectSignal()
  {
    lsdb.onLsdbModified.connect(
      [&] (std::shared_ptr<Lsa> lsa, LsdbUpdate updateType,
           const auto& namesToAdd, const auto& namesToRemove) {
        lsaPtrCheck = lsa;
        updateTypeCheck = updateType;
        namesToAddCheck = namesToAdd;
        namesToRemoveCheck = namesToRemove;
        updateHappened = true;
      }
    );
  }

public:
  ndn::DummyClientFace face;
  ConfParameter conf;
  DummyConfFileProcessor confProcessor;
  Lsdb lsdb;

  LsdbUpdate updateTypeCheck = LsdbUpdate::INSTALLED;
  std::list<ndn::Name> namesToAddCheck;
  std::list<ndn::Name> namesToRemoveCheck;
  std::shared_ptr<Lsa> lsaPtrCheck = nullptr;
  bool updateHappened = false;
};

BOOST_FIXTURE_TEST_SUITE(TestLsdb, LsdbFixture)

BOOST_AUTO_TEST_CASE(LsdbSync)
{
  ndn::Name interestName("/ndn/NLSR/LSA/cs/%C1.Router/router2/name");
  uint64_t oldSeqNo = 82;

  ndn::Name oldInterestName = interestName;
  oldInterestName.appendNumber(oldSeqNo);

  lsdb.expressInterest(oldInterestName, 0, 0);
  advanceClocks(10_ms);

  std::vector<ndn::Interest>& interests = face.sentInterests;

  BOOST_REQUIRE(interests.size() > 0);

  bool didFindInterest = false;
  for (const auto& interest : interests) {
    didFindInterest = didFindInterest || interest.getName() == oldInterestName;
  }

  BOOST_CHECK(didFindInterest);
  interests.clear();

  auto deadline = ndn::time::steady_clock::now() + ndn::time::seconds(LSA_REFRESH_TIME_MAX);

  // Simulate an LSA interest timeout
  lsdb.onFetchLsaError(ndn::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT, "Timeout",
                       oldInterestName, 0, deadline, interestName, oldSeqNo);
  advanceClocks(10_ms);

  BOOST_REQUIRE(interests.size() > 0);

  didFindInterest = false;
  for (const auto& interest : interests) {
    didFindInterest = didFindInterest || interest.getName() == oldInterestName;
  }

  BOOST_CHECK(didFindInterest);
  interests.clear();

  uint64_t newSeqNo = 83;

  ndn::Name newInterestName = interestName;
  newInterestName.appendNumber(newSeqNo);

  lsdb.expressInterest(newInterestName, 0, 0);
  advanceClocks(10_ms);

  BOOST_REQUIRE(interests.size() > 0);

  didFindInterest = false;
  for (const auto& interest : interests) {
    didFindInterest = didFindInterest || interest.getName() == newInterestName;
  }

  BOOST_CHECK(didFindInterest);

  interests.clear();

  // Simulate an LSA interest timeout where the sequence number is outdated
  lsdb.onFetchLsaError(ndn::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT, "Timeout",
                       oldInterestName, 0, deadline, interestName, oldSeqNo);
  advanceClocks(10_ms);

  // Interest should not be expressed for outdated sequence number
  BOOST_CHECK_EQUAL(interests.size(), 0);
}

BOOST_AUTO_TEST_CASE(LsdbSegmentedData)
{
  // Add a lot of NameLSAs to exceed max packet size
  ndn::Name originRouter("/ndn/site/%C1.Router/this-router");

  auto nameLsa = lsdb.findLsa<NameLsa>(originRouter);
  BOOST_REQUIRE(nameLsa != nullptr);
  uint64_t seqNo = nameLsa->getSeqNo();

  ndn::Name prefix("/ndn/edu/memphis/netlab/research/nlsr/test/prefix/");

  int nPrefixes = 0;
  while (nameLsa->wireEncode().size() < ndn::MAX_NDN_PACKET_SIZE) {
    nameLsa->addName(ndn::Name(prefix).appendNumber(++nPrefixes));
    break;
  }
  lsdb.installLsa(nameLsa);

  // Create another Lsdb and expressInterest
  ndn::DummyClientFace face2(m_io, m_keyChain, {true, true});
  face.linkTo(face2);

  ConfParameter conf2(face2, m_keyChain);
  std::string config = R"CONF(
              trust-anchor
                {
                  type any
                }
            )CONF";
  conf2.getValidator().load(config, "config-file-from-string");

  Lsdb lsdb2(face2, m_keyChain, conf2);

  advanceClocks(ndn::time::milliseconds(10), 10);

  ndn::Name interestName("/localhop/ndn/nlsr/LSA/site/%C1.Router/this-router/NAME");
  interestName.appendNumber(seqNo);
  lsdb2.expressInterest(interestName, 0/*= timeout count*/, 0);

  advanceClocks(ndn::time::milliseconds(200), 20);

  isFirstNameLsaEqual(lsdb2);
}

BOOST_AUTO_TEST_CASE(SegmentLsaData)
{
  ndn::Name originRouter("/ndn/site/%C1.Router/this-router");

  auto lsa = lsdb.findLsa<NameLsa>(originRouter);
  uint64_t seqNo = lsa->getSeqNo();

  ndn::Name prefix("/ndn/edu/memphis/netlab/research/nlsr/test/prefix/");

  int nPrefixes = 0;
  while (lsa->wireEncode().size() < ndn::MAX_NDN_PACKET_SIZE) {
    lsa->addName(ndn::Name(prefix).appendNumber(++nPrefixes));
  }
  lsdb.installLsa(lsa);

  ndn::Block expectedDataContent = lsa->wireEncode();

  ndn::Name interestName("/localhop/ndn/nlsr/LSA/site/%C1.Router/this-router/NAME/");
  interestName.appendNumber(seqNo);

  ndn::DummyClientFace face2(m_io, m_keyChain, {true, true});
  face.linkTo(face2);

  auto fetcher = ndn::SegmentFetcher::start(face2, ndn::Interest(interestName),
                                            ndn::security::getAcceptAllValidator());
  fetcher->onComplete.connect([&expectedDataContent] (ndn::ConstBufferPtr bufferPtr) {
                                ndn::Block block(bufferPtr);
                                BOOST_CHECK_EQUAL(expectedDataContent, block);
                              });

  advanceClocks(ndn::time::milliseconds(1), 100);
  fetcher->stop();
}

BOOST_AUTO_TEST_CASE(ReceiveSegmentedLsaData)
{
  ndn::Name router("/ndn/cs/%C1.Router/router1");
  uint64_t seqNo = 12;
  NamePrefixList prefixList;

  NameLsa lsa(router, seqNo, ndn::time::system_clock::now(), prefixList);

  ndn::Name prefix("/prefix/");

  for (int nPrefixes = 0; nPrefixes < 3; ++nPrefixes) {
    lsa.addName(ndn::Name(prefix).appendNumber(nPrefixes));
  }

  ndn::Name interestName("/localhop/ndn/nlsr/LSA/cs/%C1.Router/router1/NAME/");
  interestName.appendNumber(seqNo);

  ndn::Block block = lsa.wireEncode();
  lsdb.afterFetchLsa(block.getBuffer(), interestName);

  auto foundLsa = std::static_pointer_cast<NameLsa>(lsdb.findLsa(lsa.getOriginRouter(), lsa.getType()));
  BOOST_REQUIRE(foundLsa != nullptr);

  BOOST_CHECK_EQUAL(foundLsa->wireEncode(), lsa.wireEncode());
}

BOOST_AUTO_TEST_CASE(LsdbRemoveAndExists)
{
  auto testTimePoint = ndn::time::system_clock::now();
  NamePrefixList npl1;

  std::string s1 = "name1";
  std::string s2 = "name2";
  std::string router1 = "/router1/1";

  npl1.insert(s1);
  npl1.insert(s2);

  // For NameLsa lsType is name.
  // 12 is seqNo, randomly generated.
  // 1800 seconds is the default life time.
  NameLsa nlsa1(router1, 12, testTimePoint, npl1);

  Lsdb& lsdb1(lsdb);

  lsdb1.installLsa(std::make_shared<NameLsa>(nlsa1));

  BOOST_CHECK(lsdb1.doesLsaExist(router1, Lsa::Type::NAME));

  lsdb1.removeLsa(router1, Lsa::Type::NAME);

  BOOST_CHECK_EQUAL(lsdb1.doesLsaExist(router1, Lsa::Type::NAME), false);
}

BOOST_AUTO_TEST_CASE(InstallNameLsa)
{
  // Install lsa with name1 and name2
  ndn::Name name1("/ndn/name1");
  ndn::Name name2("/ndn/name2");

  NamePrefixList prefixes;
  prefixes.insert(name1);
  prefixes.insert(name2);

  std::string otherRouter("/ndn/site/%C1.router/other-router");
  const auto MAX_TIME = ndn::time::system_clock::time_point::max();

  NameLsa lsa(otherRouter, 1, MAX_TIME, prefixes);
  lsdb.installLsa(std::make_shared<NameLsa>(lsa));

  BOOST_REQUIRE_EQUAL(lsdb.doesLsaExist(otherRouter, Lsa::Type::NAME), true);
  NamePrefixList& nameList = std::static_pointer_cast<NameLsa>(lsdb.findLsa(otherRouter, Lsa::Type::NAME))->getNpl();

  BOOST_CHECK_EQUAL(nameList, prefixes);
  //areNamePrefixListsEqual(nameList, prefixes);

  // Add a prefix: name3
  ndn::Name name3("/ndn/name3");
  prefixes.insert(name3);

  NameLsa addLsa(otherRouter, 2, MAX_TIME, prefixes);
  lsdb.installLsa(std::make_shared<NameLsa>(addLsa));

  // Lsa should include name1, name2, and name3
  BOOST_CHECK_EQUAL(nameList, prefixes);

  // Remove a prefix: name2
  prefixes.remove(name2);

  NameLsa removeLsa(otherRouter, 3, MAX_TIME, prefixes);
  lsdb.installLsa(std::make_shared<NameLsa>(removeLsa));

  // Lsa should include name1 and name3
  BOOST_CHECK_EQUAL(nameList, prefixes);

  // Add and remove a prefix: add name2, remove name3
  prefixes.insert(name2);
  prefixes.remove(name3);

  NameLsa addAndRemoveLsa(otherRouter, 4, MAX_TIME, prefixes);
  lsdb.installLsa(std::make_shared<NameLsa>(addAndRemoveLsa));

  // Lsa should include name1 and name2
  BOOST_CHECK_EQUAL(nameList, prefixes);

  // Install a completely new list of prefixes
  ndn::Name name4("/ndn/name4");
  ndn::Name name5("/ndn/name5");

  NamePrefixList newPrefixes;
  newPrefixes.insert(name4);
  newPrefixes.insert(name5);

  NameLsa newLsa(otherRouter, 5, MAX_TIME, newPrefixes);
  lsdb.installLsa(std::make_shared<NameLsa>(newLsa));

  // Lsa should include name4 and name5
  BOOST_CHECK_EQUAL(nameList, newPrefixes);
}

BOOST_AUTO_TEST_CASE(TestIsLsaNew)
{
  ndn::Name originRouter("/ndn/memphis/%C1.Router/other-router");

  // Install Name LSA
  NamePrefixList nameList;
  NameLsa lsa(originRouter, 999, ndn::time::system_clock::time_point::max(), nameList);

  lsdb.installLsa(std::make_shared<NameLsa>(lsa));

  // Lower NameLSA sequence number
  uint64_t lowerSeqNo = 998;
  BOOST_CHECK(!lsdb.isLsaNew(originRouter, Lsa::Type::NAME, lowerSeqNo));

  // Same NameLSA sequence number
  uint64_t sameSeqNo = 999;
  BOOST_CHECK(!lsdb.isLsaNew(originRouter, Lsa::Type::NAME, sameSeqNo));

  // Higher NameLSA sequence number
  uint64_t higherSeqNo = 1000;
  BOOST_CHECK(lsdb.isLsaNew(originRouter, Lsa::Type::NAME, higherSeqNo));
}

BOOST_AUTO_TEST_CASE(LsdbSignals)
{
  connectSignal();
  auto testTimePoint = ndn::time::system_clock::now() + 3600_s;
  ndn::Name router2("/router2");
  AdjLsa adjLsa(router2, 12, testTimePoint, 2, conf.getAdjacencyList());
  std::shared_ptr<Lsa> lsaPtr = std::make_shared<AdjLsa>(adjLsa);
  lsdb.installLsa(lsaPtr);
  checkSignalResult(LsdbUpdate::INSTALLED, lsaPtr, {}, {});

  adjLsa.setSeqNo(13);
  updateHappened = false;
  lsaPtr = std::make_shared<AdjLsa>(adjLsa);
  lsdb.installLsa(lsaPtr);
  BOOST_CHECK(!updateHappened);

  Adjacent adj("Neighbor1");
  adjLsa.setSeqNo(14);
  adjLsa.addAdjacent(adj);
  lsaPtr = std::make_shared<AdjLsa>(adjLsa);
  lsdb.installLsa(lsaPtr);
  checkSignalResult(LsdbUpdate::UPDATED, lsaPtr, {}, {});

  lsdb.removeLsa(lsaPtrCheck->getOriginRouter(), Lsa::Type::ADJACENCY);
  checkSignalResult(LsdbUpdate::REMOVED, lsaPtr, {}, {});

  // Name LSA
  NamePrefixList npl1{"name1", "name2"};
  NameLsa nameLsa(router2, 12, testTimePoint, npl1);
  lsaPtr = std::make_shared<NameLsa>(nameLsa);
  lsdb.installLsa(lsaPtr);
  checkSignalResult(LsdbUpdate::INSTALLED, lsaPtr, {}, {});

  nameLsa.setSeqNo(13);
  lsaPtr = std::make_shared<NameLsa>(nameLsa);
  lsdb.installLsa(lsaPtr);
  BOOST_CHECK(!updateHappened);

  NamePrefixList npl2{"name2", "name3"};
  NameLsa nameLsa2(router2, 14, testTimePoint, npl2);
  lsaPtr = std::make_shared<NameLsa>(nameLsa2);
  lsdb.installLsa(lsaPtr);
  checkSignalResult(LsdbUpdate::UPDATED, lsaPtr, {"name3"}, {"name1"});

  lsdb.removeLsa(lsaPtrCheck->getOriginRouter(), Lsa::Type::NAME);
  checkSignalResult(LsdbUpdate::REMOVED, lsaPtr, {}, {});

  // Coordinate LSA
  lsaPtr = std::make_shared<CoordinateLsa>(CoordinateLsa("router1", 12, testTimePoint, 2.5, {30}));
  lsdb.installLsa(lsaPtr);
  checkSignalResult(LsdbUpdate::INSTALLED, lsaPtr, {}, {});

  lsaPtr = std::make_shared<CoordinateLsa>(CoordinateLsa("router1", 13, testTimePoint, 2.5, {30}));
  lsdb.installLsa(lsaPtr);
  BOOST_CHECK(!updateHappened);

  lsaPtr = std::make_shared<CoordinateLsa>(CoordinateLsa("router1", 14, testTimePoint, 2.5, {40}));
  lsdb.installLsa(lsaPtr);
  checkSignalResult(LsdbUpdate::UPDATED, lsaPtr, {}, {});

  lsdb.removeLsa(lsaPtrCheck->getOriginRouter(), Lsa::Type::COORDINATE);
  checkSignalResult(LsdbUpdate::REMOVED, lsaPtr, {}, {});
}

BOOST_AUTO_TEST_SUITE_END() // TestLsdb

} // namespace test
} // namespace nlsr
