/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2020,  The University of Memphis,
 *                           Regents of the University of California
 *
 * 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 "adjacent.hpp"
#include "logger.hpp"
#include "tlv/tlv-nlsr.hpp"

namespace nlsr {

INIT_LOGGER(Adjacent);

const double Adjacent::DEFAULT_LINK_COST = 10.0;
const double Adjacent::NON_ADJACENT_COST = -12345;

Adjacent::Adjacent()
    : m_name()
    , m_faceUri()
    , m_linkCost(DEFAULT_LINK_COST)
    , m_status(STATUS_INACTIVE)
    , m_interestTimedOutNo(0)
    , m_faceId(0)
{
}

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

Adjacent::Adjacent(const ndn::Name& an)
    : m_name(an)
    , m_faceUri()
    , m_linkCost(DEFAULT_LINK_COST)
    , m_status(STATUS_INACTIVE)
    , m_interestTimedOutNo(0)
    , m_faceId(0)
  {
  }

Adjacent::Adjacent(const ndn::Name& an, const ndn::FaceUri& faceUri, double lc,
                   Status s, uint32_t iton, uint64_t faceId)
    : m_name(an)
    , m_faceUri(faceUri)
    , m_status(s)
    , m_interestTimedOutNo(iton)
    , m_faceId(faceId)
  {
    this->setLinkCost(lc);
  }

void
Adjacent::setLinkCost(double lc)
{
  // NON_ADJACENT_COST is a negative value and is used for nodes that aren't direct neighbors.
  // But for direct/active neighbors, the cost cannot be negative.
  if (lc < 0 && lc != NON_ADJACENT_COST)
  {
    NLSR_LOG_ERROR(" Neighbor's link-cost cannot be negative");
    BOOST_THROW_EXCEPTION(ndn::tlv::Error("Neighbor's link-cost cannot be negative"));
  }

  m_linkCost = lc;
}

NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Adjacent);

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

  totalLength += prependDoubleBlock(encoder, ndn::tlv::nlsr::Cost, m_linkCost);

  totalLength += prependStringBlock(encoder, ndn::tlv::nlsr::Uri, m_faceUri.toString());

  totalLength += m_name.wireEncode(encoder);

  totalLength += encoder.prependVarNumber(totalLength);
  totalLength += encoder.prependVarNumber(ndn::tlv::nlsr::Adjacency);

  return totalLength;
}

const ndn::Block&
Adjacent::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
Adjacent::wireDecode(const ndn::Block& wire)
{
  m_name.clear();
  m_faceUri = ndn::FaceUri();
  m_linkCost = 0;

  m_wire = wire;

  if (m_wire.type() != ndn::tlv::nlsr::Adjacency) {
    BOOST_THROW_EXCEPTION(Error("Expected Adjacency Block, but Block is of a different type: #" +
                                ndn::to_string(m_wire.type())));
  }

  m_wire.parse();

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

  if (val != m_wire.elements_end() && val->type() == ndn::tlv::Name) {
    m_name.wireDecode(*val);
    ++val;
  }
  else {
    BOOST_THROW_EXCEPTION(Error("Missing required Name field"));
  }

  if (val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::Uri) {
    m_faceUri = ndn::FaceUri(readString(*val));
    ++val;
  }
  else {
    BOOST_THROW_EXCEPTION(Error("Missing required Uri field"));
  }

  if (val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::Cost) {
    m_linkCost = ndn::encoding::readDouble(*val);
    ++val;
  }
  else {
    BOOST_THROW_EXCEPTION(Error("Missing required Cost field"));
  }
}

bool
Adjacent::operator==(const Adjacent& adjacent) const
{
  return (m_name == adjacent.getName()) &&
         (m_faceUri == adjacent.getFaceUri()) &&
         (std::abs(m_linkCost - adjacent.getLinkCost()) <
          std::numeric_limits<double>::epsilon());
}

bool
Adjacent::operator<(const Adjacent& adjacent) const
{
  auto linkCost = adjacent.getLinkCost();
  return std::tie(m_name, m_linkCost) <
         std::tie(adjacent.getName(), linkCost);
}

std::ostream&
operator<<(std::ostream& os, const Adjacent& adjacent)
{
  os << "Adjacent: " << adjacent.m_name
     << "\n\t\tConnecting FaceUri: " << adjacent.m_faceUri
     << "\n\t\tLink cost: " << adjacent.m_linkCost
     << "\n\t\tStatus: " << adjacent.m_status
     << "\n\t\tInterest Timed Out: " << adjacent.m_interestTimedOutNo << std::endl;
  return os;
}

} // namespace nlsr
