/* -*- 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 NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
#define NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP

#include "../encoding/block.hpp"
#include "../encoding/encoding-buffer.hpp"
#include "../encoding/tlv-nfd.hpp"
#include "../name.hpp"

namespace ndn {
namespace nfd {

// NextHopRecord := NEXT-HOP-RECORD TLV-LENGTH
//                    FaceId
//                    Cost

class NextHopRecord
{
public:
  class Error : public Tlv::Error
  {
  public:
    Error(const std::string& what) : Tlv::Error(what)
    {
    }
  };

  NextHopRecord()
    : m_faceId(std::numeric_limits<uint64_t>::max())
    , m_cost(0)
  {
  }

  explicit
  NextHopRecord(const Block& block)
  {
    wireDecode(block);
  }

  uint64_t
  getFaceId() const
  {
    return m_faceId;
  }

  NextHopRecord&
  setFaceId(uint64_t faceId)
  {
    m_faceId = faceId;
    m_wire.reset();
    return *this;
  }

  uint64_t
  getCost() const
  {
    return m_cost;
  }

  NextHopRecord&
  setCost(uint64_t cost)
  {
    m_cost = cost;
    m_wire.reset();
    return *this;
  }

  template<bool T>
  size_t
  wireEncode(EncodingImpl<T>& block) const
  {
    size_t totalLength = 0;
    totalLength += prependNonNegativeIntegerBlock(block,
                                                  ndn::tlv::nfd::Cost,
                                                  m_cost);

    totalLength += prependNonNegativeIntegerBlock(block,
                                                  ndn::tlv::nfd::FaceId,
                                                  m_faceId);

    totalLength += block.prependVarNumber(totalLength);
    totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
    return totalLength;
  }

  const Block&
  wireEncode() const
  {
    if (m_wire.hasWire())
      {
        return m_wire;
      }

    EncodingEstimator estimator;
    size_t estimatedSize = wireEncode(estimator);

    EncodingBuffer buffer(estimatedSize, 0);
    wireEncode(buffer);

    m_wire = buffer.block();
    return m_wire;
  }

  void
  wireDecode(const Block& wire)
  {
    m_faceId = std::numeric_limits<uint64_t>::max();
    m_cost = 0;

    m_wire = wire;

    if (m_wire.type() != tlv::nfd::NextHopRecord)
      {
        std::stringstream error;
        error << "Requested decoding of NextHopRecord, but Block is of a different type: #"
              << m_wire.type();
        throw Error(error.str());
      }
    m_wire.parse();

    Block::element_const_iterator val = m_wire.elements_begin();
    if (val == m_wire.elements_end())
      {
        throw Error("Unexpected end of NextHopRecord");
      }
    else if (val->type() != tlv::nfd::FaceId)
      {
        std::stringstream error;
        error << "Expected FaceId, but Block is of a different type: #"
              << val->type();
        throw Error(error.str());
      }
    m_faceId = readNonNegativeInteger(*val);
    ++val;

    if (val == m_wire.elements_end())
      {
        throw Error("Unexpected end of NextHopRecord");
      }
    else if (val->type() != tlv::nfd::Cost)
      {
        std::stringstream error;
        error << "Expected Cost, but Block is of a different type: #"
              << error.str();
        throw Error(error.str());
      }
    m_cost = readNonNegativeInteger(*val);
  }


private:
  uint64_t m_faceId;
  uint64_t m_cost;

  mutable Block m_wire;
};


// FibEntry      := FIB-ENTRY-TYPE TLV-LENGTH
//                    Name
//                    NextHopRecord*

class FibEntry
{
public:
    class Error : public Tlv::Error
    {
    public:
      Error(const std::string& what) : Tlv::Error(what)
      {
      }
    };

  FibEntry()
  {
  }

  explicit
  FibEntry(const Block& block)
  {
    wireDecode(block);
  }

  const Name&
  getPrefix() const
  {
    return m_prefix;
  }

  FibEntry&
  setPrefix(const Name& prefix)
  {
    m_prefix = prefix;
    m_wire.reset();
    return *this;
  }

  const std::list<NextHopRecord>&
  getNextHopRecords() const
  {
    return m_nextHopRecords;
  }

  FibEntry&
  addNextHopRecord(const NextHopRecord& nextHopRecord)
  {
    m_nextHopRecords.push_back(nextHopRecord);
    m_wire.reset();
    return *this;
  }

  template<typename T>
  FibEntry&
  setNextHopRecords(const T& begin, const T& end)
  {
    m_nextHopRecords.clear();
    m_nextHopRecords.assign(begin, end);
    m_wire.reset();
    return *this;
  }

  template<bool T>
  size_t
  wireEncode(EncodingImpl<T>& block) const
  {
    size_t totalLength = 0;

    for (std::list<NextHopRecord>::const_iterator i = m_nextHopRecords.begin();
         i != m_nextHopRecords.end();
         ++i)
      {
        totalLength += i->wireEncode(block);
      }

    totalLength += m_prefix.wireEncode(block);
    totalLength += block.prependVarNumber(totalLength);
    totalLength += block.prependVarNumber(tlv::nfd::FibEntry);

    return totalLength;
  }

  const Block&
  wireEncode() const
  {
    if (m_wire.hasWire())
      {
        return m_wire;
      }

    EncodingEstimator estimator;
    size_t estimatedSize = wireEncode(estimator);

    EncodingBuffer buffer(estimatedSize, 0);
    wireEncode(buffer);

    m_wire = buffer.block();

    return m_wire;
  }

  void
  wireDecode(const Block& wire)
  {
    m_prefix.clear();
    m_nextHopRecords.clear();

    m_wire = wire;

    if (m_wire.type() != tlv::nfd::FibEntry)
      {
        std::stringstream error;
        error << "Requested decoding of FibEntry, but Block is of a different type: #"
              << m_wire.type();
        throw Error(error.str());
      }

    m_wire.parse();

    Block::element_const_iterator val = m_wire.elements_begin();
    if (val == m_wire.elements_end())
      {
        throw Error("Unexpected end of FibEntry");
      }
    else if (val->type() != Tlv::Name)
      {
        std::stringstream error;
        error << "Expected Name, but Block is of a different type: #"
              << val->type();
        throw Error(error.str());
      }
    m_prefix.wireDecode(*val);
    ++val;

    for (; val != m_wire.elements_end(); ++val)
      {
        if (val->type() != tlv::nfd::NextHopRecord)
          {
            std::stringstream error;
            error << "Expected NextHopRecords, but Block is of a different type: #"
                  << val->type();
            throw Error(error.str());
          }
        m_nextHopRecords.push_back(NextHopRecord(*val));
      }
  }

private:
  Name m_prefix;
  std::list<NextHopRecord> m_nextHopRecords;

  mutable Block m_wire;
};

} // namespace nfd
} // namespace ndn

#endif // NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
