/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (C) 2014 Named Data Networking Project
 * See COPYING for copyright and distribution information.
 */

#ifndef NFD_FACE_LOCAL_FACE_HPP
#define NFD_FACE_LOCAL_FACE_HPP

#include "face.hpp"

namespace nfd {

/* \brief indicates a feature in LocalControlHeader
 */
enum LocalControlHeaderFeature
{
  /// any feature
  LOCAL_CONTROL_HEADER_FEATURE_ANY,
  /// in-faceid
  LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID,
  /// out-faceid
  LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID,
  /// upper bound of enum
  LOCAL_CONTROL_HEADER_FEATURE_MAX
};


/** \brief represents a face
 */
class LocalFace : public Face
{
public:
  explicit
  LocalFace(const FaceUri& uri);

  /** \brief get whether a LocalControlHeader feature is enabled
   *
   *  \param feature The feature. Cannot be LOCAL_CONTROL_HEADER_FEATURE_MAX
   *  LOCAL_CONTROL_HEADER_FEATURE_ANY returns true if any feature is enabled.
   */
  bool
  isLocalControlHeaderEnabled(LocalControlHeaderFeature feature =
                              LOCAL_CONTROL_HEADER_FEATURE_ANY) const;

  /** \brief enable or disable a LocalControlHeader feature
   *
   *  \param feature The feature. Cannot be LOCAL_CONTROL_HEADER_FEATURE_ANY
   *                                     or LOCAL_CONTROL_HEADER_FEATURE_MAX
   */
  void
  setLocalControlHeaderFeature(LocalControlHeaderFeature feature, bool enabled = true);

protected:
  // statically overridden from Face

  /** \brief Decode block into Interest/Data, considering potential LocalControlHeader
   *
   *  If LocalControlHeader is present, the encoded data is filtered out, based
   *  on enabled features on the face.
   */
  bool
  decodeAndDispatchInput(const Block& element);

  // LocalFace-specific methods

  /** \brief Check if LocalControlHeader needs to be included, taking into account
   *         both set parameters in supplied LocalControlHeader and features
   *         enabled on the local face.
   */
  bool
  isEmptyFilteredLocalControlHeader(const ndn::nfd::LocalControlHeader& header) const;

  /** \brief Create LocalControlHeader, considering enabled features
   */
  template<class Packet>
  Block
  filterAndEncodeLocalControlHeader(const Packet& packet);

private:
  std::vector<bool> m_localControlHeaderFeatures;
};

inline
LocalFace::LocalFace(const FaceUri& uri)
  : Face(uri, true)
  , m_localControlHeaderFeatures(LOCAL_CONTROL_HEADER_FEATURE_MAX)
{
}

inline bool
LocalFace::isLocalControlHeaderEnabled(LocalControlHeaderFeature feature) const
{
  BOOST_ASSERT(feature < m_localControlHeaderFeatures.size());
  return m_localControlHeaderFeatures[feature];
}

inline void
LocalFace::setLocalControlHeaderFeature(LocalControlHeaderFeature feature, bool enabled/* = true*/)
{
  BOOST_ASSERT(feature > LOCAL_CONTROL_HEADER_FEATURE_ANY &&
               feature < m_localControlHeaderFeatures.size());
  m_localControlHeaderFeatures[feature] = enabled;

  BOOST_STATIC_ASSERT(LOCAL_CONTROL_HEADER_FEATURE_ANY == 0);
  m_localControlHeaderFeatures[LOCAL_CONTROL_HEADER_FEATURE_ANY] =
    std::find(m_localControlHeaderFeatures.begin() + 1,
              m_localControlHeaderFeatures.end(), true) <
              m_localControlHeaderFeatures.end();
  // 'find(..) < .end()' instead of 'find(..) != .end()' due to LLVM Bug 16816
}

inline bool
LocalFace::decodeAndDispatchInput(const Block& element)
{
  const Block& payload = ndn::nfd::LocalControlHeader::getPayload(element);

  // If received LocalControlHeader, but it is not enabled on the face
  if ((&payload != &element) && !this->isLocalControlHeaderEnabled())
    return false;

  if (payload.type() == tlv::Interest)
    {
      shared_ptr<Interest> i = make_shared<Interest>();
      i->wireDecode(payload);
      if (&payload != &element)
        {
          i->getLocalControlHeader().wireDecode(element,
            false,
            this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
        }

      this->onReceiveInterest(*i);
    }
  else if (payload.type() == tlv::Data)
    {
      shared_ptr<Data> d = make_shared<Data>();
      d->wireDecode(payload);

      /// \todo Uncomment and correct the following when we have more
      ///       options in LocalControlHeader that apply for incoming
      ///       Data packets (if ever)
      // if (&payload != &element)
      //   {
      //
      //     d->getLocalControlHeader().wireDecode(element,
      //       false,
      //       false);
      //   }

      this->onReceiveData(*d);
    }
  else
    return false;

  return true;
}

inline bool
LocalFace::isEmptyFilteredLocalControlHeader(const ndn::nfd::LocalControlHeader& header) const
{
  if (!this->isLocalControlHeaderEnabled())
    return true;

  return header.empty(this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID),
                      false);
}

template<class Packet>
inline Block
LocalFace::filterAndEncodeLocalControlHeader(const Packet& packet)
{
  return packet.getLocalControlHeader().wireEncode(packet,
           this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID),
           false);
}

} // namespace nfd

#endif // NFD_FACE_LOCAL_FACE_HPP
