/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#ifndef NDN_MGMT_NFD_RIB_ENTRY_HPP
#define NDN_MGMT_NFD_RIB_ENTRY_HPP

#include "rib-flags.hpp"
#include "../../encoding/block.hpp"
#include "../../name.hpp"
#include "../../util/time.hpp"

namespace ndn {
namespace nfd {

/**
 * \ingroup management
 * \brief represents a route in a RibEntry
 *
 * A route indicates the availability of content via a certain face and
 * provides meta-information about the face.
 *
 * \sa https://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Route
 */
class Route : public RibFlagsTraits<Route>
{
public:
  class Error : public tlv::Error
  {
  public:
    explicit
    Error(const std::string& what)
      : tlv::Error(what)
    {
    }
  };

  Route();

  explicit
  Route(const Block& block);

  uint64_t
  getFaceId() const
  {
    return m_faceId;
  }

  Route&
  setFaceId(uint64_t faceId);

  uint64_t
  getOrigin() const
  {
    return m_origin;
  }

  /** @brief set Origin
   *  @param origin a code defined in ndn::nfd::RouteOrigin
   */
  Route&
  setOrigin(uint64_t origin);

  uint64_t
  getCost() const
  {
    return m_cost;
  }

  Route&
  setCost(uint64_t cost);

  uint64_t
  getFlags() const
  {
    return m_flags;
  }

  /** @brief set route inheritance flags
   *  @param flags a bitwise OR'ed code from ndn::nfd::RouteFlags
   */
  Route&
  setFlags(uint64_t flags);

  bool
  hasExpirationPeriod() const
  {
    return !!m_expirationPeriod;
  }

  time::milliseconds
  getExpirationPeriod() const
  {
    return m_expirationPeriod ? *m_expirationPeriod : time::milliseconds::max();
  }

  Route&
  setExpirationPeriod(time::milliseconds expirationPeriod);

  Route&
  unsetExpirationPeriod();

  template<encoding::Tag TAG>
  size_t
  wireEncode(EncodingImpl<TAG>& block) const;

  const Block&
  wireEncode() const;

  void
  wireDecode(const Block& block);

private:
  uint64_t m_faceId;
  uint64_t m_origin;
  uint64_t m_cost;
  uint64_t m_flags;
  optional<time::milliseconds> m_expirationPeriod;

  mutable Block m_wire;
};

bool
operator==(const Route& a, const Route& b);

inline bool
operator!=(const Route& a, const Route& b)
{
  return !(a == b);
}

std::ostream&
operator<<(std::ostream& os, const Route& route);


/**
 * \ingroup management
 * \brief represents an item in NFD RIB dataset
 *
 * A RIB entry contains one or more routes for a name prefix
 *
 * \sa https://redmine.named-data.net/projects/nfd/wiki/RibMgmt#RIB-Dataset
 */
class RibEntry
{
public:
  class Error : public tlv::Error
  {
  public:
    explicit
    Error(const std::string& what)
      : tlv::Error(what)
    {
    }
  };

  RibEntry();

  explicit
  RibEntry(const Block& block);

  const Name&
  getName() const
  {
    return m_prefix;
  }

  RibEntry&
  setName(const Name& prefix);

  const std::vector<Route>&
  getRoutes() const
  {
    return m_routes;
  }

  template<typename InputIt>
  RibEntry&
  setRoutes(InputIt first, InputIt last)
  {
    m_routes.assign(first, last);
    m_wire.reset();
    return *this;
  }

  RibEntry&
  addRoute(const Route& route);

  RibEntry&
  clearRoutes();

  template<encoding::Tag TAG>
  size_t
  wireEncode(EncodingImpl<TAG>& block) const;

  const Block&
  wireEncode() const;

  void
  wireDecode(const Block& block);

private:
  Name m_prefix;
  std::vector<Route> m_routes;

  mutable Block m_wire;
};

bool
operator==(const RibEntry& a, const RibEntry& b);

inline bool
operator!=(const RibEntry& a, const RibEntry& b)
{
  return !(a == b);
}

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

} // namespace nfd
} // namespace ndn

#endif // NDN_MGMT_NFD_RIB_ENTRY_HPP
