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

#ifndef NFD_TESTS_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
#define NFD_TESTS_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP

#include "mgmt/fib-enumeration-publisher.hpp"

#include "mgmt/app-face.hpp"
#include "mgmt/internal-face.hpp"
#include "table/fib.hpp"
#include "table/name-tree.hpp"

#include "tests/test-common.hpp"
#include "../face/dummy-face.hpp"

#include <ndn-cpp-dev/encoding/tlv.hpp>

namespace nfd {
namespace tests {

static inline uint64_t
readNonNegativeIntegerType(const Block& block,
                           uint32_t type)
{
  if (block.type() == type)
    {
      return readNonNegativeInteger(block);
    }
  std::stringstream error;
  error << "Expected type " << type << " got " << block.type();
  throw ndn::Tlv::Error(error.str());
}

static inline uint64_t
checkedReadNonNegativeIntegerType(Block::element_const_iterator& i,
                                  Block::element_const_iterator end,
                                  uint32_t type)
{
  if (i != end)
    {
      const Block& block = *i;
      ++i;
      return readNonNegativeIntegerType(block, type);
    }
  std::stringstream error;
  error << "Unexpected end of Block while attempting to read type #"
        << type;
  throw ndn::Tlv::Error(error.str());
}

class FibEnumerationPublisherFixture : public BaseFixture
{
public:

  FibEnumerationPublisherFixture()
    : m_fib(m_nameTree)
    , m_face(make_shared<InternalFace>())
    , m_publisher(m_fib, m_face, "/localhost/nfd/FibEnumerationPublisherFixture")
    , m_finished(false)
  {
  }

  virtual
  ~FibEnumerationPublisherFixture()
  {
  }

  bool
  hasNextHopWithCost(const fib::NextHopList& nextHops,
                     FaceId faceId,
                     uint64_t cost)
  {
    for (fib::NextHopList::const_iterator i = nextHops.begin();
         i != nextHops.end();
         ++i)
      {
        if (i->getFace()->getId() == faceId && i->getCost() == cost)
          {
            return true;
          }
      }
    return false;
  }

  bool
  entryHasPrefix(const shared_ptr<fib::Entry> entry, const Name& prefix)
  {
    return entry->getPrefix() == prefix;
  }

  void
  validateFibEntry(const Block& entry)
  {
    entry.parse();

    Block::element_const_iterator i = entry.elements_begin();
    BOOST_REQUIRE(i != entry.elements_end());


    BOOST_REQUIRE(i->type() == ndn::Tlv::Name);
    Name prefix(*i);
    ++i;

    std::set<shared_ptr<fib::Entry> >::const_iterator referenceIter =
      std::find_if(m_referenceEntries.begin(), m_referenceEntries.end(),
                   boost::bind(&FibEnumerationPublisherFixture::entryHasPrefix,
                               this, _1, prefix));

    BOOST_REQUIRE(referenceIter != m_referenceEntries.end());

    const shared_ptr<fib::Entry>& reference = *referenceIter;
    BOOST_REQUIRE_EQUAL(prefix, reference->getPrefix());

    // 0 or more next hop records
    size_t nRecords = 0;
    const fib::NextHopList& referenceNextHops = reference->getNextHops();
    for (; i != entry.elements_end(); ++i)
      {
        const ndn::Block& nextHopRecord = *i;
        BOOST_REQUIRE(nextHopRecord.type() == ndn::tlv::nfd::NextHopRecord);
        nextHopRecord.parse();

        Block::element_const_iterator j = nextHopRecord.elements_begin();

        FaceId faceId =
          checkedReadNonNegativeIntegerType(j,
                                            entry.elements_end(),
                                            ndn::tlv::nfd::FaceId);

        uint64_t cost =
          checkedReadNonNegativeIntegerType(j,
                                            entry.elements_end(),
                                            ndn::tlv::nfd::Cost);

        BOOST_REQUIRE(hasNextHopWithCost(referenceNextHops, faceId, cost));

        BOOST_REQUIRE(j == nextHopRecord.elements_end());
        nRecords++;
      }
    BOOST_REQUIRE_EQUAL(nRecords, referenceNextHops.size());

    BOOST_REQUIRE(i == entry.elements_end());
    m_referenceEntries.erase(referenceIter);
  }

  void
  decodeFibEntryBlock(const Data& data)
  {
    Block payload = data.getContent();

    m_buffer.appendByteArray(payload.value(), payload.value_size());

    BOOST_CHECK_NO_THROW(data.getName()[-1].toSegment());
    if (data.getFinalBlockId() != data.getName()[-1])
      {
        return;
      }

    // wrap the FIB Entry blocks in a single Content TLV for easy parsing
    m_buffer.prependVarNumber(m_buffer.size());
    m_buffer.prependVarNumber(ndn::Tlv::Content);

    ndn::Block parser(m_buffer.buf(), m_buffer.size());
    parser.parse();

    BOOST_REQUIRE_EQUAL(parser.elements_size(), m_referenceEntries.size());

    for (Block::element_const_iterator i = parser.elements_begin();
         i != parser.elements_end();
         ++i)
      {
        if (i->type() != ndn::tlv::nfd::FibEntry)
          {
            BOOST_FAIL("expected fib entry, got type #" << i->type());
          }

        validateFibEntry(*i);
      }
    m_finished = true;
  }

protected:
  NameTree m_nameTree;
  Fib m_fib;
  shared_ptr<InternalFace> m_face;
  FibEnumerationPublisher m_publisher;
  ndn::EncodingBuffer m_buffer;
  std::set<shared_ptr<fib::Entry> > m_referenceEntries;

protected:
  bool m_finished;
};

} // namespace tests
} // namespace nfd

#endif // NFD_TESTS_MGMT_FIB_ENUMERATION_PUBLISHER_COMMON_HPP
