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

#include "encoding/block.hpp"
#include "encoding/encoding-buffer.hpp"
#include "name-component.hpp"
#include "util/time.hpp"

#include <list>

namespace ndn {

const time::milliseconds DEFAULT_FRESHNESS_PERIOD = time::milliseconds::zero();

/**
 * A MetaInfo holds the meta info which is signed inside the data packet.
 *
 * The class allows experimentation with application-defined meta information blocks,
 * which slightly violates NDN-TLV specification.  When using the application-defined
 * meta information blocks be aware that this may result in packet drop (NFD and
 * previous versions of ndn-cxx will gracefully accept such packet).
 *
 * The following definition of MetaInfo block is assumed in this implementation (compared
 * to the NDN-TLV spec, definition extended to allow optional AppMetaInfo TLV blocks):
 *
 *     MetaInfo ::= META-INFO-TYPE TLV-LENGTH
 *                    ContentType?
 *                    FreshnessPeriod?
 *                    FinalBlockId?
 *                    AppMetaInfo*
 *
 *     AppMetaInfo ::= any TLV block with type in the restricted application range [128, 252]
 *
 * Note that AppMetaInfo blocks are application-defined and must have TLV type from
 * the restricted application range [128, 252].
 */
class MetaInfo
{
public:
  class Error : public tlv::Error
  {
  public:
    using tlv::Error::Error;
  };

  MetaInfo();

  /**
   * @brief Create from wire encoding
   */
  explicit
  MetaInfo(const Block& block);

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

  const Block&
  wireEncode() const;

  void
  wireDecode(const Block& wire);

public: // getter/setter
  /** @brief return ContentType
   *
   *  If ContentType element is omitted, returns \c tlv::ContentType_Blob.
   */
  uint32_t
  getType() const
  {
    return m_type;
  }

  /** @brief set ContentType
   *  @param type a number defined in \c tlv::ContentTypeValue
   */
  MetaInfo&
  setType(uint32_t type);

  /** @brief return FreshnessPeriod
   *
   *  If FreshnessPeriod element is omitted, returns \c DEFAULT_FRESHNESS_PERIOD.
   */
  time::milliseconds
  getFreshnessPeriod() const
  {
    return m_freshnessPeriod;
  }

  /** @brief set FreshnessPeriod
   *  @throw std::invalid_argument specified FreshnessPeriod is negative
   */
  MetaInfo&
  setFreshnessPeriod(time::milliseconds freshnessPeriod);

  /** @brief return FinalBlockId
   */
  const optional<name::Component>&
  getFinalBlock() const
  {
    return m_finalBlockId;
  }

  /** @brief set FinalBlockId
   */
  MetaInfo&
  setFinalBlock(optional<name::Component> finalBlockId);

  /** @brief return FinalBlockId
   *  @deprecated use @c getFinalBlock
   *
   *  If FinalBlockId element is omitted, returns a default-constructed @c name::Component.
   *  This is indistinguishable from having an empty GenericNameComponent as FinalBlockId.
   */
  [[deprecated("use getFinalBlock")]]
  name::Component
  getFinalBlockId() const
  {
    return getFinalBlock().value_or(name::Component());
  }

  /** @brief set FinalBlockId
   *  @deprecated use @c setFinalBlock
   *
   *  Passing a default-constructed @c name::Component removes FinalBlockId element.
   *  This API does not support adding an empty GenericNameComponent as FinalBlockId.
   */
  [[deprecated("use setFinalBlock")]]
  MetaInfo&
  setFinalBlockId(const name::Component& finalBlockId);

public: // app-defined MetaInfo items
  /**
   * @brief Get all app-defined MetaInfo items
   *
   * @note Warning: Experimental API, which may change or disappear in the future
   *
   * @note If MetaInfo is decoded from wire and setType, setFreshnessPeriod, or setFinalBlock
   *       is called before *AppMetaInfo, all app-defined blocks will be lost
   */
  const std::list<Block>&
  getAppMetaInfo() const;

  /**
   * @brief Set app-defined MetaInfo items
   *
   * This method will replace all existing app-defined MetaInfo items, if they existed.
   *
   * @throw Error if some block in @p info has type not in the application range
   *              (http://named-data.net/doc/ndn-tlv/types.html)
   *
   * @note Warning: Experimental API, which may change or disappear in the future
   *
   * @note If MetaInfo is decoded from wire and setType, setFreshnessPeriod, or setFinalBlock
   *       is called before *AppMetaInfo, all app-defined blocks will be lost
   */
  MetaInfo&
  setAppMetaInfo(const std::list<Block>& info);

  /**
   * @brief Add an app-defined MetaInfo item
   *
   * @throw Error if @p block has type not in the application range
   *              (http://named-data.net/doc/ndn-tlv/types.html)
   *
   * @note Warning: Experimental API, which may change or disappear in the future
   *
   * @note If MetaInfo is decoded from wire and setType, setFreshnessPeriod, or setFinalBlock
   *       is called before *AppMetaInfo, all app-defined blocks will be lost
   */
  MetaInfo&
  addAppMetaInfo(const Block& block);

  /**
   * @brief Remove a first app-defined MetaInfo item with type @p tlvType
   *
   * @return true if an item was deleted
   *
   * @note Warning: Experimental API, which may change or disappear in the future
   *
   * @note If MetaInfo is decoded from wire and setType, setFreshnessPeriod, or setFinalBlock
   *       is called before *AppMetaInfo, all app-defined blocks will be lost
   */
  bool
  removeAppMetaInfo(uint32_t tlvType);

  /**
   * @brief Find a first app-defined MetaInfo item of type @p tlvType
   *
   * @return NULL if an item is not found, otherwise const pointer to the item
   *
   * @throw Error if @p tlvType is not in the application range
   *              (http://named-data.net/doc/ndn-tlv/types.html)
   *
   * @note Warning: Experimental API, which may change or disappear in the future
   *
   * @note If MetaInfo is decoded from wire and setType, setFreshnessPeriod, or setFinalBlock
   *       is called before *AppMetaInfo, all app-defined blocks will be lost
   */
  const Block*
  findAppMetaInfo(uint32_t tlvType) const;

public: // EqualityComparable concept
  bool
  operator==(const MetaInfo& other) const;

  bool
  operator!=(const MetaInfo& other) const;

private:
  uint32_t m_type;
  time::milliseconds m_freshnessPeriod;
  optional<name::Component> m_finalBlockId;
  std::list<Block> m_appMetaInfo;

  mutable Block m_wire;
};

NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(MetaInfo);

std::ostream&
operator<<(std::ostream& os, const MetaInfo& info);

inline bool
MetaInfo::operator==(const MetaInfo& other) const
{
  return wireEncode() == other.wireEncode();
}

inline bool
MetaInfo::operator!=(const MetaInfo& other) const
{
  return !(*this == other);
}

} // namespace ndn

#endif // NDN_META_INFO_HPP
