/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2019 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_INTEREST_HPP
#define NDN_INTEREST_HPP

#include "ndn-cxx/delegation-list.hpp"
#include "ndn-cxx/name.hpp"
#include "ndn-cxx/selectors.hpp"
#include "ndn-cxx/detail/packet-base.hpp"
#include "ndn-cxx/util/time.hpp"

#include <boost/logic/tribool.hpp>

namespace ndn {

class Data;

/** @var const unspecified_duration_type DEFAULT_INTEREST_LIFETIME;
 *  @brief default value for InterestLifetime
 */
const time::milliseconds DEFAULT_INTEREST_LIFETIME = 4_s;

/** @brief Represents an Interest packet.
 */
class Interest : public PacketBase, public std::enable_shared_from_this<Interest>
{
public:
  class Error : public tlv::Error
  {
  public:
    using tlv::Error::Error;
  };

  /** @brief Construct an Interest with given @p name and @p lifetime.
   *  @throw std::invalid_argument @p lifetime is negative
   *  @warning In certain contexts that use `Interest::shared_from_this()`, Interest must be created
   *           using `make_shared`. Otherwise, `shared_from_this()` will trigger undefined behavior.
   */
  explicit
  Interest(const Name& name = Name(), time::milliseconds lifetime = DEFAULT_INTEREST_LIFETIME);

  /** @brief Construct an Interest by decoding from @p wire.
   *  @warning In certain contexts that use `Interest::shared_from_this()`, Interest must be created
   *           using `make_shared`. Otherwise, `shared_from_this()` will trigger undefined behavior.
   */
  explicit
  Interest(const Block& wire);

  /** @brief Prepend wire encoding to @p encoder.
   */
  template<encoding::Tag TAG>
  size_t
  wireEncode(EncodingImpl<TAG>& encoder) const;

  /** @brief Encode to a @c Block.
   *
   *  Encodes into NDN Packet Format v0.3 if ApplicationParameters element is present, in which
   *  case Selectors are not encoded. Otherwise, encodes into NDN Packet Format v0.2.
   */
  const Block&
  wireEncode() const;

  /** @brief Decode from @p wire in NDN Packet Format v0.2 or v0.3.
   */
  void
  wireDecode(const Block& wire);

  /** @brief Check if this instance has cached wire encoding.
   */
  bool
  hasWire() const
  {
    return m_wire.hasWire();
  }

  /** @brief Return a URI-like string that represents the Interest.
   *
   *  The string starts with `getName().toUri()`.
   *  If the Interest contains selectors, they are included as a query string.
   *  Example: "/test/name?ndn.MustBeFresh=1"
   */
  std::string
  toUri() const;

public: // matching
  /** @brief Check if Interest, including selectors, matches the given @p name
   *  @param name The name to be matched. If this is a Data name, it shall contain the
   *              implicit digest component
   */
  bool
  matchesName(const Name& name) const;

  /** @brief Check if Interest can be satisfied by @p data.
   *
   *  This method considers Name, MinSuffixComponents, MaxSuffixComponents,
   *  PublisherPublicKeyLocator, and Exclude.
   *  This method does not consider ChildSelector and MustBeFresh.
   */
  bool
  matchesData(const Data& data) const;

  /** @brief Check if Interest matches @p other interest
   *
   *  Interest matches @p other if both have the same name, selectors, and link.  Other fields
   *  (e.g., Nonce) may be different.
   *
   *  @todo Implement distinguishing Interests by forwarding hint. The current implementation
   *        checks only name+selectors (Issue #3162).
   */
  bool
  matchesInterest(const Interest& other) const;

public: // element access
  const Name&
  getName() const
  {
    return m_name;
  }

  Interest&
  setName(const Name& name)
  {
    m_name = name;
    m_wire.reset();
    return *this;
  }

  /** @brief Declare the default CanBePrefix setting of the application.
   *
   *  As part of transitioning to NDN Packet Format v0.3, the default setting for CanBePrefix
   *  will be changed from "true" to "false". Application developers are advised to review all
   *  Interests expressed by their application and decide what CanBePrefix setting is appropriate
   *  for each Interest, to avoid breaking changes when the transition occurs. Application may
   *  either set CanBePrefix on a per-Interest basis, or declare a default CanBePrefix setting for
   *  all Interests expressed by the application using this function. If an application neither
   *  declares a default nor sets CanBePrefix on every Interest, Interest::wireEncode will print a
   *  one-time warning message.
   *
   *  @note This function should not be used in libraries or in ndn-cxx unit tests.
   *  @sa https://redmine.named-data.net/projects/nfd/wiki/Packet03Transition
   */
  static void
  setDefaultCanBePrefix(bool canBePrefix)
  {
    s_defaultCanBePrefix = canBePrefix;
  }

  /** @brief Check whether the CanBePrefix element is present.
   *
   *  This is a getter for the CanBePrefix element as defined in NDN Packet Format v0.3.
   *  In this implementation, it is mapped to the closest v0.2 semantics:
   *  MaxSuffixComponents=1 means CanBePrefix is absent.
   */
  bool
  getCanBePrefix() const
  {
    return m_selectors.getMaxSuffixComponents() != 1;
  }

  /** @brief Add or remove CanBePrefix element.
   *  @param canBePrefix whether CanBePrefix element should be present.
   *
   *  This is a setter for the CanBePrefix element as defined in NDN Packet Format v0.3.
   *  In this implementation, it is mapped to the closest v0.2 semantics:
   *  MaxSuffixComponents=1 means CanBePrefix is absent.
   */
  Interest&
  setCanBePrefix(bool canBePrefix)
  {
    m_selectors.setMaxSuffixComponents(canBePrefix ? -1 : 1);
    m_wire.reset();
    m_isCanBePrefixSet = true;
    return *this;
  }

  /** @brief Check whether the MustBeFresh element is present.
   *
   *  This is a getter for the MustBeFresh element as defined in NDN Packet Format v0.3.
   *  In this implementation, it is mapped to the closest v0.2 semantics and appears as
   *  MustBeFresh element under Selectors.
   */
  bool
  getMustBeFresh() const
  {
    return m_selectors.getMustBeFresh();
  }

  /** @brief Add or remove MustBeFresh element.
   *  @param mustBeFresh whether MustBeFresh element should be present.
   *
   *  This is a setter for the MustBeFresh element as defined in NDN Packet Format v0.3.
   *  In this implementation, it is mapped to the closest v0.2 semantics and appears as
   *  MustBeFresh element under Selectors.
   */
  Interest&
  setMustBeFresh(bool mustBeFresh)
  {
    m_selectors.setMustBeFresh(mustBeFresh);
    m_wire.reset();
    return *this;
  }

  const DelegationList&
  getForwardingHint() const
  {
    return m_forwardingHint;
  }

  Interest&
  setForwardingHint(const DelegationList& value);

  /** @brief Modify ForwardingHint in-place.
   *  @tparam Modifier a unary function that accepts DelegationList&
   *
   *  This is equivalent to, but more efficient (avoids copying) than:
   *  @code
   *  auto fh = interest.getForwardingHint();
   *  modifier(fh);
   *  interest.setForwardingHint(fh);
   *  @endcode
   */
  template<typename Modifier>
  Interest&
  modifyForwardingHint(const Modifier& modifier)
  {
    modifier(m_forwardingHint);
    m_wire.reset();
    return *this;
  }

  /** @brief Check if the Nonce element is present.
   */
  bool
  hasNonce() const
  {
    return m_nonce.has_value();
  }

  /** @brief Get nonce value.
   *
   *  If nonce was not present, it is added and assigned a random value.
   */
  uint32_t
  getNonce() const;

  /** @brief Set nonce value.
   */
  Interest&
  setNonce(uint32_t nonce);

  /** @brief Change nonce value.
   *
   *  If the Nonce element is present, the new nonce value will differ from the old value.
   *  If the Nonce element is not present, this method does nothing.
   */
  void
  refreshNonce();

  time::milliseconds
  getInterestLifetime() const
  {
    return m_interestLifetime;
  }

  /** @brief Set Interest's lifetime
   *  @throw std::invalid_argument @p lifetime is negative
   */
  Interest&
  setInterestLifetime(time::milliseconds lifetime);

  bool
  hasApplicationParameters() const
  {
    return !m_parameters.empty();
  }

  const Block&
  getApplicationParameters() const
  {
    return m_parameters;
  }

  /** @brief Set ApplicationParameters from a Block
   *
   *  If the block is default-constructed, this will set a zero-length
   *  ApplicationParameters element.
   *  Else, if the block's TLV-TYPE is ApplicationParameters, it will be
   *  used directly as this Interest's ApplicationParameters element.
   *  Else, the block will be nested into an ApplicationParameters element.
   *  @return a reference to this Interest
   */
  Interest&
  setApplicationParameters(const Block& parameters);

  /** @brief Copy ApplicationParameters from raw buffer
   *
   *  @param buffer pointer to the first octet of parameters
   *  @param bufferSize size of the raw buffer
   *  @return a reference to this Interest
   */
  Interest&
  setApplicationParameters(const uint8_t* buffer, size_t bufferSize);

  /** @brief Set ApplicationParameters from a wire buffer
   *
   *  @param buffer buffer containing the parameters, must not be nullptr
   *  @return a reference to this Interest
   */
  Interest&
  setApplicationParameters(ConstBufferPtr buffer);

  /** @brief Remove the ApplicationParameters element from this Interest
   *
   *  @post hasApplicationParameters() == false
   */
  Interest&
  unsetApplicationParameters();

public: // Selectors (deprecated)
  /** @brief Check if Interest has any selector present.
   */
  [[deprecated]]
  bool
  hasSelectors() const
  {
    return !m_selectors.empty();
  }

  [[deprecated]]
  const Selectors&
  getSelectors() const
  {
    return m_selectors;
  }

  [[deprecated]]
  Interest&
  setSelectors(const Selectors& selectors)
  {
    m_selectors = selectors;
    m_wire.reset();
    return *this;
  }

  [[deprecated]]
  int
  getMinSuffixComponents() const
  {
    return m_selectors.getMinSuffixComponents();
  }

  [[deprecated]]
  Interest&
  setMinSuffixComponents(int minSuffixComponents)
  {
    m_selectors.setMinSuffixComponents(minSuffixComponents);
    m_wire.reset();
    return *this;
  }

  [[deprecated]]
  int
  getMaxSuffixComponents() const
  {
    return m_selectors.getMaxSuffixComponents();
  }

  [[deprecated]]
  Interest&
  setMaxSuffixComponents(int maxSuffixComponents)
  {
    m_selectors.setMaxSuffixComponents(maxSuffixComponents);
    m_wire.reset();
    return *this;
  }

  [[deprecated]]
  const KeyLocator&
  getPublisherPublicKeyLocator() const
  {
    return m_selectors.getPublisherPublicKeyLocator();
  }

  [[deprecated]]
  Interest&
  setPublisherPublicKeyLocator(const KeyLocator& keyLocator)
  {
    m_selectors.setPublisherPublicKeyLocator(keyLocator);
    m_wire.reset();
    return *this;
  }

  [[deprecated]]
  const Exclude&
  getExclude() const
  {
    return m_selectors.getExclude();
  }

  [[deprecated]]
  Interest&
  setExclude(const Exclude& exclude)
  {
    m_selectors.setExclude(exclude);
    m_wire.reset();
    return *this;
  }

  [[deprecated]]
  int
  getChildSelector() const
  {
    return m_selectors.getChildSelector();
  }

  [[deprecated]]
  Interest&
  setChildSelector(int childSelector)
  {
    m_selectors.setChildSelector(childSelector);
    m_wire.reset();
    return *this;
  }

private:
  /** @brief Prepend wire encoding to @p encoder in NDN Packet Format v0.2.
   */
  template<encoding::Tag TAG>
  size_t
  encode02(EncodingImpl<TAG>& encoder) const;

  /** @brief Prepend wire encoding to @p encoder in NDN Packet Format v0.3.
   */
  template<encoding::Tag TAG>
  size_t
  encode03(EncodingImpl<TAG>& encoder) const;

  /** @brief Decode @c m_wire as NDN Packet Format v0.2.
   *  @retval true decoding successful.
   *  @retval false decoding failed due to structural error.
   *  @throw tlv::Error decoding error within a sub-element.
   */
  bool
  decode02();

  /** @brief Decode @c m_wire as NDN Packet Format v0.3.
   *  @throw tlv::Error decoding error.
   */
  void
  decode03();

#ifdef NDN_CXX_HAVE_TESTS
public:
  /** @brief If true, not setting CanBePrefix results in an error in wireEncode().
   */
  static bool s_errorIfCanBePrefixUnset;
#endif // NDN_CXX_HAVE_TESTS

private:
  static boost::logic::tribool s_defaultCanBePrefix;

  Name m_name;
  Selectors m_selectors; // NDN Packet Format v0.2 only
  mutable bool m_isCanBePrefixSet;
  mutable optional<uint32_t> m_nonce;
  time::milliseconds m_interestLifetime;
  DelegationList m_forwardingHint;
  Block m_parameters; // NDN Packet Format v0.3 only

  mutable Block m_wire;

  friend bool operator==(const Interest& lhs, const Interest& rhs);
};

NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Interest);

std::ostream&
operator<<(std::ostream& os, const Interest& interest);

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

inline bool
operator!=(const Interest& lhs, const Interest& rhs)
{
  return !(lhs == rhs);
}

} // namespace ndn

#endif // NDN_INTEREST_HPP
