/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2017,  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 "name-prefix-table-entry.hpp"

#include "common.hpp"
#include "nexthop.hpp"
#include "logger.hpp"

namespace nlsr {

INIT_LOGGER("NamePrefixTableEntry");

void
NamePrefixTableEntry::generateNhlfromRteList()
{
  m_nexthopList.reset();
  for (auto iterator = m_rteList.begin(); iterator != m_rteList.end(); ++iterator) {
    for (auto nhItr = (*iterator)->getNexthopList().getNextHops().begin();
         nhItr != (*iterator)->getNexthopList().getNextHops().end();
         ++nhItr) {
      m_nexthopList.addNextHop((*nhItr));
    }
  }
}

uint64_t
NamePrefixTableEntry::removeRoutingTableEntry(std::shared_ptr<RoutingTablePoolEntry>
                                              entryPtr)
{
  auto iterator = std::find(m_rteList.begin(), m_rteList.end(), entryPtr);

  if (iterator != m_rteList.end()) {
    (*iterator)->decrementUseCount();
    // Remove this NamePrefixEntry from the RoutingTablePoolEntry
    (*iterator)->namePrefixTableEntries.erase(getNamePrefix());
    m_rteList.erase(iterator);
  }
  else {
    NLSR_LOG_ERROR("Routing entry for: " << entryPtr->getDestination()
               << " not found in NPT entry: " << getNamePrefix());
  }
  return entryPtr->getUseCount();
}

void
NamePrefixTableEntry::addRoutingTableEntry(std::shared_ptr<RoutingTablePoolEntry>
                                           entryPtr)
{
  auto iterator = std::find(m_rteList.begin(), m_rteList.end(), entryPtr);

  // Ensure that this is a new entry
  if (iterator == m_rteList.end()) {
    // Adding a new routing entry to the NPT entry
    entryPtr->incrementUseCount();
    m_rteList.push_back(entryPtr);
  }
  // Note: we don't need to update in the else case because these are
  // pointers, and they are centrally-located in the NPT and will all
  // be updated there.
}

void
NamePrefixTableEntry::writeLog()
{
  NLSR_LOG_DEBUG("Name: " << m_namePrefix);
  for (auto it = m_rteList.begin(); it != m_rteList.end(); ++it) {
    NLSR_LOG_DEBUG("Destination: " << (*it)->getDestination());
    NLSR_LOG_DEBUG("Nexthops: ");
    (*it)->getNexthopList().writeLog();
  }
  m_nexthopList.writeLog();
}

bool
operator==(const NamePrefixTableEntry& lhs, const NamePrefixTableEntry& rhs)
{
  return (lhs.getNamePrefix() == rhs.getNamePrefix());
}

bool
operator==(const NamePrefixTableEntry& lhs, const ndn::Name& rhs)
{
  return (lhs.getNamePrefix() == rhs);
}

std::ostream&
operator<<(std::ostream& os, const NamePrefixTableEntry& entry)
{
  os << "Name: " << entry.getNamePrefix() << "\n";

  for (const std::shared_ptr<RoutingTablePoolEntry> entryPtr : entry.getRteList()) {
    os << "Destination: " << entryPtr->getDestination() << "\n";
  }

  return os;
}

} // namespace nlsr
