/* -*- 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 {
    _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()
{
  _LOG_DEBUG("Name: " << m_namePrefix);
  for (auto it = m_rteList.begin(); it != m_rteList.end(); ++it) {
    _LOG_DEBUG("Destination: " << (*it)->getDestination());
    _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
