/* -*- 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/>.
 **/

#ifndef NLSR_NAME_PREFIX_TABLE_ENTRY_HPP
#define NLSR_NAME_PREFIX_TABLE_ENTRY_HPP

#include "routing-table-pool-entry.hpp"

#include "test-access-control.hpp"

#include <list>
#include <utility>

namespace nlsr {

class NamePrefixTableEntry
{
public:
  NamePrefixTableEntry()
  {
  }

  NamePrefixTableEntry(const ndn::Name& namePrefix)
    : m_namePrefix(namePrefix)
    , m_nexthopList()
  {
  }

  const ndn::Name&
  getNamePrefix() const
  {
    return m_namePrefix;
  }

  const std::list<std::shared_ptr<RoutingTablePoolEntry>>&
  getRteList() const
  {
    return m_rteList;
  }

  /*! \brief Resets the next hop lists of all routing table entries
   * that advertise this name prefix.
   */
  void
  resetRteListNextHop()
  {
    if (m_rteList.size() > 0) {
      for (auto it = m_rteList.begin(); it != m_rteList.end(); ++it) {
        (*it)->getNexthopList().reset();
      }
    }
  }

  size_t
  getRteListSize()
  {
    return m_rteList.size();
  }

  NexthopList&
  getNexthopList()
  {
    return m_nexthopList;
  }

  /*! \brief Collect all next-hops that are advertised by this entry's
   * routing entries.
   */
  void
  generateNhlfromRteList();

  /*! \brief Removes a routing entry from this NPT entry.
   * \return The number of NPTs using the just-removed routing entry.
   */
  uint64_t
  removeRoutingTableEntry(std::shared_ptr<RoutingTablePoolEntry> rtpePtr);

  /*! \brief Adds a routing entry to this NPT entry.
   * \param rtpePtr The routing entry.
   *
   * Adds a routing table pool entry to this NPT entry's list
   * (reminder: each RTPE has a next-hop list). They are used to
   * calculate this entry's overall next-hop list.
   */
  void
  addRoutingTableEntry(std::shared_ptr<RoutingTablePoolEntry> rtpePtr);

  void
  writeLog();

private:
  ndn::Name m_namePrefix;

PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  std::list<std::shared_ptr<RoutingTablePoolEntry>> m_rteList;
  NexthopList m_nexthopList;

};

bool
operator==(const NamePrefixTableEntry& lhs, const NamePrefixTableEntry& rhs);

bool
operator==(const NamePrefixTableEntry& lhs, const ndn::Name& rhs);

std::ostream&
operator<<(std::ostream& os, const NamePrefixTableEntry& entry);

} // namespace nlsr

#endif // NLSR_NAME_PREFIX_TABLE_ENTRY_HPP
