/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (C) 2014 Named Data Networking Project
 * See COPYING for copyright and distribution information.
 */

#ifndef NFD_TESTS_MGMT_FACE_STATUS_PUBLISHER_COMMON_HPP
#define NFD_TESTS_MGMT_FACE_STATUS_PUBLISHER_COMMON_HPP

#include "mgmt/face-status-publisher.hpp"
#include "mgmt/app-face.hpp"
#include "mgmt/internal-face.hpp"
#include "fw/forwarder.hpp"
#include "../face/dummy-face.hpp"

#include "tests/test-common.hpp"

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

namespace nfd {
namespace tests {

class TestCountersFace : public DummyFace
{
public:

  TestCountersFace()
  {
  }

  virtual
  ~TestCountersFace()
  {
  }

  void
  setCounters(FaceCounter inInterest,
              FaceCounter inData,
              FaceCounter outInterest,
              FaceCounter outData)
  {
    FaceCounters& counters = getMutableCounters();
    counters.getInInterest() = inInterest;
    counters.getInData() = inData;
    counters.getOutInterest() = outInterest;
    counters.getOutData() = outData;
  }


};

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);
    }
  throw ndn::Tlv::Error("Unexpected end of FaceStatus");
}

class FaceStatusPublisherFixture : public BaseFixture
{
public:

  FaceStatusPublisherFixture()
    : m_table(m_forwarder)
    , m_face(make_shared<InternalFace>())
    , m_publisher(m_table, m_face, "/localhost/nfd/FaceStatusPublisherFixture")
    , m_finished(false)
  {

  }

  virtual
  ~FaceStatusPublisherFixture()
  {

  }

  void
  add(shared_ptr<Face> face)
  {
    m_table.add(face);
  }

  void
  validateFaceStatus(const Block& status, const shared_ptr<Face>& reference)
  {
    const FaceCounters& counters = reference->getCounters();

    FaceId faceId = INVALID_FACEID;
    std::string uri;
    FaceCounter inInterest = 0;
    FaceCounter inData = 0;
    FaceCounter outInterest = 0;
    FaceCounter outData = 0;

    status.parse();

    for (Block::element_const_iterator i = status.elements_begin();
         i != status.elements_end();
         ++i)
      {
        // parse a full set of FaceStatus sub-blocks
        faceId =
          checkedReadNonNegativeIntegerType(i,
                                            status.elements_end(),
                                            ndn::tlv::nfd::FaceId);

        BOOST_REQUIRE_EQUAL(faceId, reference->getId());

        BOOST_REQUIRE(i->type() == ndn::tlv::nfd::Uri);

        uri.append(reinterpret_cast<const char*>(i->value()), i->value_size());
        ++i;

        BOOST_REQUIRE(i != status.elements_end());

        BOOST_REQUIRE_EQUAL(uri, reference->getUri().toString());

        inInterest =
          checkedReadNonNegativeIntegerType(i,
                                            status.elements_end(),
                                            ndn::tlv::nfd::NInInterests);

        BOOST_REQUIRE_EQUAL(inInterest, counters.getInInterest());

        inData =
          checkedReadNonNegativeIntegerType(i,
                                            status.elements_end(),
                                            ndn::tlv::nfd::NInDatas);

        BOOST_REQUIRE_EQUAL(inData, counters.getInData());

        outInterest =
          checkedReadNonNegativeIntegerType(i,
                                            status.elements_end(),
                                            ndn::tlv::nfd::NOutInterests);
        BOOST_REQUIRE_EQUAL(outInterest, counters.getOutInterest());

        outData =
          readNonNegativeIntegerType(*i,
                                     ndn::tlv::nfd::NOutDatas);

        BOOST_REQUIRE_EQUAL(outData, counters.getOutData());
      }
  }

  void
  decodeFaceStatusBlock(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 Face Statuses 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_referenceFaces.size());

    std::list<shared_ptr<Face> >::const_iterator iReference = m_referenceFaces.begin();
    for (Block::element_const_iterator i = parser.elements_begin();
         i != parser.elements_end();
         ++i)
      {
        if (i->type() != ndn::tlv::nfd::FaceStatus)
          {
            BOOST_FAIL("expected face status, got type #" << i->type());
          }
        validateFaceStatus(*i, *iReference);
        ++iReference;
      }
    m_finished = true;
  }

protected:
  Forwarder m_forwarder;
  FaceTable m_table;
  shared_ptr<InternalFace> m_face;
  FaceStatusPublisher m_publisher;
  ndn::EncodingBuffer m_buffer;
  std::list<shared_ptr<Face> > m_referenceFaces;

protected:
  bool m_finished;
};

} // namespace tests
} // namespace nfd

#endif // NFD_TESTS_MGMT_FACE_STATUS_PUBLISHER_COMMON_HPP
