/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2021,  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-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");
    NDN_THROW(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) {
    NDN_THROW(Error("Adjacency", m_wire.type()));
  }

  m_wire.parse();

  auto val = m_wire.elements_begin();

  if (val != m_wire.elements_end() && val->type() == ndn::tlv::Name) {
    m_name.wireDecode(*val);
    ++val;
  }
  else {
    NDN_THROW(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 {
    NDN_THROW(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 {
    NDN_THROW(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
