/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2018,  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 "lsdb-status.hpp"
#include "tlv-nlsr.hpp"

#include <ndn-cxx/util/concepts.hpp>
#include <ndn-cxx/encoding/block-helpers.hpp>

namespace nlsr {
namespace tlv {

BOOST_CONCEPT_ASSERT((ndn::WireEncodable<LsdbStatus>));
BOOST_CONCEPT_ASSERT((ndn::WireDecodable<LsdbStatus>));
static_assert(std::is_base_of<ndn::tlv::Error, LsdbStatus::Error>::value,
              "LsdbStatus::Error must inherit from tlv::Error");

LsdbStatus::LsdbStatus()
  : m_hasAdjacencyLsas(false)
  , m_hasCoordinateLsas(false)
  , m_hasNameLsas(false)
{
}

LsdbStatus::LsdbStatus(const ndn::Block& block)
{
  wireDecode(block);
}

LsdbStatus&
LsdbStatus::addAdjacencyLsa(const AdjacencyLsa& adjacencyLsa)
{
  m_adjacencyLsas.push_back(adjacencyLsa);
  m_wire.reset();
  m_hasAdjacencyLsas = true;
  return *this;
}

LsdbStatus&
LsdbStatus::clearAdjacencyLsas()
{
  m_adjacencyLsas.clear();
  m_hasAdjacencyLsas = false;
  return *this;
}

LsdbStatus&
LsdbStatus::addCoordinateLsa(const CoordinateLsa& coordinateLsa)
{
  m_coordinateLsas.push_back(coordinateLsa);
  m_wire.reset();
  m_hasCoordinateLsas = true;
  return *this;
}

LsdbStatus&
LsdbStatus::clearCoordinateLsas()
{
  m_coordinateLsas.clear();
  m_hasCoordinateLsas = false;
  return *this;
}

LsdbStatus&
LsdbStatus::addNameLsa(const NameLsa& nameLsa)
{
  m_nameLsas.push_back(nameLsa);
  m_wire.reset();
  m_hasNameLsas = true;
  return *this;
}

LsdbStatus&
LsdbStatus::clearNameLsas()
{
  m_nameLsas.clear();
  m_hasNameLsas = false;
  return *this;
}

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

  for (std::list<NameLsa>::const_reverse_iterator it = m_nameLsas.rbegin();
       it != m_nameLsas.rend(); ++it) {
    totalLength += it->wireEncode(block);
  }

  for (std::list<CoordinateLsa>::const_reverse_iterator it = m_coordinateLsas.rbegin();
       it != m_coordinateLsas.rend(); ++it) {
    totalLength += it->wireEncode(block);
  }

  for (std::list<AdjacencyLsa>::const_reverse_iterator it = m_adjacencyLsas.rbegin();
       it != m_adjacencyLsas.rend(); ++it) {
    totalLength += it->wireEncode(block);
  }

  totalLength += block.prependVarNumber(totalLength);
  totalLength += block.prependVarNumber(ndn::tlv::nlsr::LsdbStatus);

  return totalLength;
}

NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(LsdbStatus);

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

  ndn::EncodingEstimator estimator;
  size_t estimatedSize = wireEncode(estimator);

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

  m_wire = buffer.block();

  return m_wire;
}

void
LsdbStatus::wireDecode(const ndn::Block& wire)
{
  m_adjacencyLsas.clear();
  m_coordinateLsas.clear();
  m_nameLsas.clear();

  m_hasAdjacencyLsas = false;
  m_hasCoordinateLsas = false;
  m_hasNameLsas = false;

  m_wire = wire;

  if (m_wire.type() != ndn::tlv::nlsr::LsdbStatus) {
    std::stringstream error;
    error << "Expected LsdbStatus Block, but Block is of a different type: #"
          << m_wire.type();
    BOOST_THROW_EXCEPTION(Error(error.str()));
  }

  m_wire.parse();

  ndn::Block::element_const_iterator val = m_wire.elements_begin();

  for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::AdjacencyLsa; ++val) {
    m_adjacencyLsas.push_back(AdjacencyLsa(*val));
    m_hasAdjacencyLsas = true;
  }

  for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::CoordinateLsa; ++val) {
    m_coordinateLsas.push_back(CoordinateLsa(*val));
    m_hasCoordinateLsas = true;
  }

  for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::NameLsa; ++val) {
    m_nameLsas.push_back(NameLsa(*val));
    m_hasNameLsas = true;
  }

  if (val != m_wire.elements_end()) {
    std::stringstream error;
    error << "Expected the end of elements, but Block is of a different type: #"
          << val->type();
    BOOST_THROW_EXCEPTION(Error(error.str()));
  }
}

std::ostream&
operator<<(std::ostream& os, const LsdbStatus& lsdbStatus)
{
  os << "LsdbStatus(";

  bool isFirst = true;

  for (const auto& adjacencyLsa : lsdbStatus.getAdjacencyLsas()) {
    if (isFirst) {
      isFirst = false;
    }
    else {
      os << ", ";
    }

    os << adjacencyLsa;
  }

  for (const auto& coordinateLsa : lsdbStatus.getCoordinateLsas()) {
    if (isFirst) {
      isFirst = false;
    }
    else {
      os << ", ";
    }

    os << coordinateLsa;
  }

  for (const auto& nameLsa : lsdbStatus.getNameLsas()) {
    if (isFirst) {
      isFirst = false;
    }
    else {
      os << ", ";
    }

    os << nameLsa;
  }

  os << ")";

  return os;
}

} // namespace tlv
} // namespace nlsr
