/* -*- 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 "statistics.hpp"
#include "hello-protocol.hpp"
#include "lsdb.hpp"
#include "nlsr.hpp"

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

#include <boost/lexical_cast.hpp>

namespace nlsr {
namespace test {

class StatisticsFixture : public IoKeyChainFixture
{
public:
  StatisticsFixture()
    : face(m_io, m_keyChain)
    , conf(face, m_keyChain)
    , confProcessor(conf)
    , nlsr(face, m_keyChain, conf)
    , lsdb(nlsr.m_lsdb)
    , hello(nlsr.m_helloProtocol)
    , collector(nlsr.m_statsCollector)
  {
    // Otherwise code coverage node fails with default 60 seconds lifetime
    conf.setSyncInterestLifetime(1000);

    m_keyChain.createIdentity(conf.getRouterPrefix());

    this->advanceClocks(ndn::time::milliseconds(1), 10);
    face.sentInterests.clear();
  }

  /*!
   * \brief Checks if lsa interest was received and data for interest was sent
   *
   * \param interestPrefix is an interest name prefix
   * \param lsaType indicates whether the lsa is a name, adjacency, or coordinate
   * \param seqNo sequence number that will be appended to an interest name
   * \param receivedInterestType is the specific Statisitcs::PacketType interest that is received
   * \param sentDataType is the Statistics::PacketType data being sent upon interest process
   *
   * This is a general function that can be used for all three types of lsa. Calling processInterest()
   * from lsdb will cause the statsCollector to increment the incoming interest type and increment the
   * outgoing data type.
   */
  void
  receiveInterestAndCheckSentStats(const std::string& interestPrefix,
                                   const std::string& lsaType,
                                   uint32_t seqNo,
                                   Statistics::PacketType receivedInterestType,
                                   Statistics::PacketType sentDataType)
  {
    size_t rcvBefore = collector.getStatistics().get(receivedInterestType);
    size_t sentBefore = collector.getStatistics().get(sentDataType);

    ndn::Name interestName = ndn::Name(ndn::Name(interestPrefix + lsaType).appendNumber(seqNo));
    lsdb.processInterest(ndn::Name(), ndn::Interest(interestName));
    this->advanceClocks(ndn::time::milliseconds(1), 10);

    BOOST_CHECK_EQUAL(collector.getStatistics().get(receivedInterestType), rcvBefore + 1);
    BOOST_CHECK_EQUAL(collector.getStatistics().get(sentDataType), sentBefore + 1);
  }

  /*!
   * \brief Checks if statistics update after an lsa interest is sent
   *
   * \param prefix is an interest prefix
   * \param lsaType indicates whether the lsa is a name, adjacency, or coordinate
   * \param seqNo is the sequence number
   * \param statsType is a statistical PacketType
   *
   * The function is called to initiate an expressInterest call in lsdb and to check if the
   * expected statistical packetType was incremented.
   */
  void
  sendInterestAndCheckStats(const std::string& prefix,
                            const std::string& lsaType,
                            uint32_t seqNo,
                            Statistics::PacketType statsType)
  {
    size_t sentBefore = collector.getStatistics().get(statsType);

    lsdb.expressInterest(ndn::Name(prefix + lsaType).appendNumber(seqNo), 0, 0,
                         ndn::time::steady_clock::time_point::min());
    this->advanceClocks(ndn::time::milliseconds(1), 10);

    BOOST_CHECK_EQUAL(collector.getStatistics().get(statsType), sentBefore + 1);
  }

public:
  ndn::DummyClientFace face;
  ConfParameter conf;
  DummyConfFileProcessor confProcessor;
  Nlsr nlsr;

  Lsdb& lsdb;
  HelloProtocol& hello;
  StatsCollector& collector;
};

BOOST_FIXTURE_TEST_SUITE(TestStatistics, StatisticsFixture)


// A statistical PacketType is directly incremented (without signals).
BOOST_AUTO_TEST_CASE(StatsIncrement)
{
  Statistics stats;
  BOOST_CHECK_EQUAL(stats.get(Statistics::PacketType::SENT_HELLO_INTEREST), 0);
  stats.increment(Statistics::PacketType::SENT_HELLO_INTEREST);
  BOOST_CHECK_EQUAL(stats.get(Statistics::PacketType::SENT_HELLO_INTEREST), 1);
}

/*
 * After a PacketType has been incremented, the resetAll() function is called, which sets all
 * statistical packetType counts to 0
 */
BOOST_AUTO_TEST_CASE(StatsReset)
{
  Statistics stats;
  stats.increment(Statistics::PacketType::SENT_HELLO_INTEREST);
  stats.resetAll();
  BOOST_CHECK_EQUAL(stats.get(Statistics::PacketType::SENT_HELLO_INTEREST), 0);
}

/*
 * This tests hello interests and hello data statistical collection by constructing an adjacency lsa
 * and calling functions that trigger the sending and receiving hello of interests/data.
 */
BOOST_AUTO_TEST_CASE(SendHelloInterest)
{
  Adjacent other("/ndn/router/other", ndn::FaceUri("udp4://other"), 25, Adjacent::STATUS_INACTIVE, 0, 0);

  // This router's Adjacency LSA
  conf.getAdjacencyList().insert(other);

  ndn::Name otherName(other.getName());
  otherName.append("NLSR");
  otherName.append("INFO");
  otherName.append(ndn::tlv::GenericNameComponent, conf.getRouterPrefix().wireEncode());

  hello.expressInterest(otherName, 1);
  this->advanceClocks(ndn::time::milliseconds(1), 10);

  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_HELLO_INTEREST), 1);

  ndn::Name thisName(conf.getRouterPrefix());
  thisName.append("NLSR");
  thisName.append("INFO");
  thisName.append(ndn::tlv::GenericNameComponent, other.getName().wireEncode());

  ndn::Interest interest(thisName);
  hello.processInterest(ndn::Name(), interest);

  this->advanceClocks(ndn::time::milliseconds(1), 10);

  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_HELLO_INTEREST), 1);
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_HELLO_DATA), 1);

  // Receive Hello Data
  ndn::Name dataName = otherName;

  ndn::Data data(dataName);
  hello.onContentValidated(data);

  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_HELLO_DATA), 1);
}

/*
 * An interest is sent for each lsa type (name, adjacency, coordinate). The respective statistics are
 * totaled and checked.
 */
BOOST_AUTO_TEST_CASE(LsdbSendLsaInterest)
{
  const std::string interestPrefix("/localhop/ndn/nlsr/LSA/site/%C1.Router/router/");
  uint32_t seqNo = 1;

  // Adjacency LSA
  sendInterestAndCheckStats(interestPrefix, boost::lexical_cast<std::string>(Lsa::Type::ADJACENCY),
                            seqNo, Statistics::PacketType::SENT_ADJ_LSA_INTEREST);

  // Coordinate LSA
  sendInterestAndCheckStats(interestPrefix, boost::lexical_cast<std::string>(Lsa::Type::COORDINATE),
                            seqNo, Statistics::PacketType::SENT_COORD_LSA_INTEREST);

  // Name LSA
  sendInterestAndCheckStats(interestPrefix, boost::lexical_cast<std::string>(Lsa::Type::NAME),
                            seqNo, Statistics::PacketType::SENT_NAME_LSA_INTEREST);

  // 3 total lsa interests were sent
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_LSA_INTEREST), 3);
}

/*
 * Tests the statistics collected upon processing incoming lsa
 * interests and respective outgoing data. This process will trigger
 * both an increment for received lsa interest and sent lsa data.
 *
 * /sa receiveInterestAndCheckSentStats
 */
BOOST_AUTO_TEST_CASE(LsdbReceiveInterestSendData)
{
  // Adjacency LSA
  lsdb.buildAndInstallOwnAdjLsa();

  auto adjLsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
  uint32_t seqNo = adjLsa->getSeqNo();

  Adjacent adjacency("adjacency");
  adjacency.setStatus(Adjacent::STATUS_ACTIVE);

  adjLsa->addAdjacent(adjacency);

  lsdb.installLsa(adjLsa);

  const std::string interestPrefix("/localhop/ndn/nlsr/LSA/site/%C1.Router/this-router/");

  // Receive Adjacency LSA Interest
  receiveInterestAndCheckSentStats(interestPrefix,
                                   boost::lexical_cast<std::string>(Lsa::Type::ADJACENCY),
                                   seqNo,
                                   Statistics::PacketType::RCV_ADJ_LSA_INTEREST,
                                   Statistics::PacketType::SENT_ADJ_LSA_DATA);

  // Name LSA
  auto nameLsa = std::static_pointer_cast<NameLsa>(lsdb.findLsa(conf.getRouterPrefix(), Lsa::Type::NAME));
  BOOST_ASSERT(nameLsa != nullptr);

  seqNo = nameLsa->getSeqNo();

  nameLsa->addName(ndn::Name("/ndn/name"));
  lsdb.installLsa(nameLsa);

  // Receive Name LSA Interest
  receiveInterestAndCheckSentStats(interestPrefix,
                                   boost::lexical_cast<std::string>(Lsa::Type::NAME),
                                   seqNo,
                                   Statistics::PacketType::RCV_NAME_LSA_INTEREST,
                                   Statistics::PacketType::SENT_NAME_LSA_DATA);

  // // Coordinate LSA
  lsdb.buildAndInstallOwnCoordinateLsa();
  ndn::Name coorLsaKey = conf.getRouterPrefix();
  coorLsaKey.append(boost::lexical_cast<std::string>(Lsa::Type::COORDINATE));

  auto coorLsa = lsdb.findLsa<CoordinateLsa>(conf.getRouterPrefix());

  seqNo = coorLsa->getSeqNo();
  coorLsa->setCorTheta({20.0, 30.0});
  lsdb.installLsa(coorLsa);

  // Receive Adjacency LSA Interest
  receiveInterestAndCheckSentStats(interestPrefix,
                                   boost::lexical_cast<std::string>(Lsa::Type::COORDINATE),
                                   seqNo,
                                   Statistics::PacketType::RCV_COORD_LSA_INTEREST,
                                   Statistics::PacketType::SENT_COORD_LSA_DATA);

  // 3 different lsa type interests should be received
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_LSA_INTEREST), 3);

  // data should have been sent 3x, once per lsa type
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_LSA_DATA), 3);
}

/*
 * Data for each lsa type (name, adjacency, coordinate) is sent to the lsdb and statistics are
 * checked to verify the respective statistical PacketType has been received.
 */
BOOST_AUTO_TEST_CASE(LsdbReceiveData)
{
  ndn::Name routerName("/ndn/cs/%C1.Router/router1");
  uint32_t seqNo = 1;
  const auto MAX_TIME = ndn::time::system_clock::time_point::max();

  // adjacency lsa
  ndn::Name adjInterest("/localhop/ndn/nlsr/LSA/cs/%C1.Router/router1/ADJACENCY/");
  adjInterest.appendNumber(seqNo);
  AdjLsa aLsa(routerName, seqNo, MAX_TIME, 1, conf.getAdjacencyList());
  lsdb.installLsa(std::make_shared<AdjLsa>(aLsa));

  lsdb.afterFetchLsa(aLsa.wireEncode().getBuffer(), adjInterest);
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_ADJ_LSA_DATA), 1);

  // coordinate lsa
  ndn::Name coordInterest("/localhop/ndn/nlsr/LSA/cs/%C1.Router/router1/COORDINATE/");
  coordInterest.appendNumber(seqNo);
  std::vector<double> angles = {20.0, 30.0};
  CoordinateLsa cLsa(routerName, seqNo, MAX_TIME, 2.5, angles);
  lsdb.installLsa(std::make_shared<CoordinateLsa>(cLsa));

  lsdb.afterFetchLsa(cLsa.wireEncode().getBuffer(), coordInterest);
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_COORD_LSA_DATA), 1);

  // name lsa
  ndn::Name interestName("/localhop/ndn/nlsr/LSA/cs/%C1.Router/router1/NAME/");
  interestName.appendNumber(seqNo);
  NameLsa nlsa(routerName, seqNo, MAX_TIME, conf.getNamePrefixList());
  lsdb.installLsa(std::make_shared<NameLsa>(nlsa));

  lsdb.afterFetchLsa(nlsa.wireEncode().getBuffer(), interestName);
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_NAME_LSA_DATA), 1);

  // 3 lsa data types should be received
  BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_LSA_DATA), 3);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace test
} // namespace nlsr
