/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "fib-entry.hpp"
#include "encoding/block-helpers.hpp"
#include "encoding/encoding-buffer.hpp"
#include "encoding/tlv-nfd.hpp"
#include "util/concepts.hpp"

#include <boost/range/adaptor/reversed.hpp>

namespace ndn {
namespace nfd {

BOOST_CONCEPT_ASSERT((StatusDatasetItem<NextHopRecord>));
BOOST_CONCEPT_ASSERT((StatusDatasetItem<FibEntry>));

NextHopRecord::NextHopRecord()
  : m_faceId(0) // INVALID_FACEID
  , m_cost(0)
{
}

NextHopRecord::NextHopRecord(const Block& block)
{
  this->wireDecode(block);
}

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

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

template<encoding::Tag TAG>
size_t
NextHopRecord::wireEncode(EncodingImpl<TAG>& 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;
}

template size_t
NextHopRecord::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;

template size_t
NextHopRecord::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;

const Block&
NextHopRecord::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
NextHopRecord::wireDecode(const Block& block)
{
  if (block.type() != tlv::nfd::NextHopRecord) {
    BOOST_THROW_EXCEPTION(Error("expecting NextHopRecord, but Block has type " + to_string(block.type())));
  }
  m_wire = block;
  m_wire.parse();
  Block::element_const_iterator val = m_wire.elements_begin();

  if (val == m_wire.elements_end()) {
    BOOST_THROW_EXCEPTION(Error("unexpected end of NextHopRecord"));
  }
  else if (val->type() != tlv::nfd::FaceId) {
    BOOST_THROW_EXCEPTION(Error("expecting FaceId, but Block has type " + to_string(val->type())));
  }
  m_faceId = readNonNegativeInteger(*val);
  ++val;

  if (val == m_wire.elements_end()) {
    BOOST_THROW_EXCEPTION(Error("unexpected end of NextHopRecord"));
  }
  else if (val->type() != tlv::nfd::Cost) {
    BOOST_THROW_EXCEPTION(Error("expecting Cost, but Block has type " + to_string(val->type())));
  }
  m_cost = readNonNegativeInteger(*val);
  ++val;
}

bool
operator==(const NextHopRecord& a, const NextHopRecord& b)
{
  return a.getFaceId() == b.getFaceId() &&
      a.getCost() == b.getCost();
}

std::ostream&
operator<<(std::ostream& os, const NextHopRecord& nh)
{
  return os << "NextHopRecord("
            << "FaceId: " << nh.getFaceId() << ", "
            << "Cost: " << nh.getCost()
            << ")";
}

////////////////////

FibEntry::FibEntry() = default;

FibEntry::FibEntry(const Block& block)
{
  this->wireDecode(block);
}

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

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

FibEntry&
FibEntry::clearNextHopRecords()
{
  m_nextHopRecords.clear();
  m_wire.reset();
  return *this;
}

template<encoding::Tag TAG>
size_t
FibEntry::wireEncode(EncodingImpl<TAG>& block) const
{
  size_t totalLength = 0;

  for (const auto& nh : m_nextHopRecords | boost::adaptors::reversed) {
    totalLength += nh.wireEncode(block);
  }
  totalLength += m_prefix.wireEncode(block);

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

template size_t
FibEntry::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;

template size_t
FibEntry::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;

const Block&
FibEntry::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
FibEntry::wireDecode(const Block& block)
{
  if (block.type() != tlv::nfd::FibEntry) {
    BOOST_THROW_EXCEPTION(Error("expecting FibEntry, but Block has type " + to_string(block.type())));
  }
  m_wire = block;
  m_wire.parse();
  Block::element_const_iterator val = m_wire.elements_begin();

  if (val == m_wire.elements_end()) {
    BOOST_THROW_EXCEPTION(Error("unexpected end of FibEntry"));
  }
  else if (val->type() != tlv::Name) {
    BOOST_THROW_EXCEPTION(Error("expecting Name, but Block has type " + to_string(val->type())));
  }
  m_prefix.wireDecode(*val);
  ++val;

  m_nextHopRecords.clear();
  for (; val != m_wire.elements_end(); ++val) {
    if (val->type() != tlv::nfd::NextHopRecord) {
      BOOST_THROW_EXCEPTION(Error("expecting NextHopRecord, but Block has type " + to_string(val->type())));
    }
    m_nextHopRecords.emplace_back(*val);
  }
}

bool
operator==(const FibEntry& a, const FibEntry& b)
{
  const auto& aNextHops = a.getNextHopRecords();
  const auto& bNextHops = b.getNextHopRecords();

  if (a.getPrefix() != b.getPrefix() ||
      aNextHops.size() != bNextHops.size())
    return false;

  std::vector<bool> matched(bNextHops.size(), false);
  return std::all_of(aNextHops.begin(), aNextHops.end(),
                     [&] (const NextHopRecord& nh) {
                       for (size_t i = 0; i < bNextHops.size(); ++i) {
                         if (!matched[i] && bNextHops[i] == nh) {
                           matched[i] = true;
                           return true;
                         }
                       }
                       return false;
                     });
}

std::ostream&
operator<<(std::ostream& os, const FibEntry& entry)
{
  os << "FibEntry(Prefix: " << entry.getPrefix() << ",\n"
     << "         NextHops: [";

  bool first = true;
  for (const auto& nh : entry.getNextHopRecords()) {
    if (!first)
      os << ",\n                    ";
    first = false;
    os << nh;
  }
  os << "]\n";

  return os << "         )";
}

} // namespace nfd
} // namespace ndn
