/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014  Regents of the University of California,
 *                     Arizona Board of Regents,
 *                     Colorado State University,
 *                     University Pierre & Marie Curie, Sorbonne University,
 *                     Washington University in St. Louis,
 *                     Beijing Institute of Technology
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#ifndef NFD_DAEMON_FACE_LOCAL_FACE_HPP
#define NFD_DAEMON_FACE_LOCAL_FACE_HPP

#include "face.hpp"
#include <ndn-cpp-dev/management/nfd-control-parameters.hpp>

namespace nfd {

using ndn::nfd::LocalControlFeature;
using ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID;
using ndn::nfd::LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID;

/** \brief represents a face
 */
class LocalFace : public Face
{
public:
  LocalFace(const FaceUri& remoteUri, const FaceUri& localUri);

  /** \brief get whether any LocalControlHeader feature is enabled
   *
   * \returns true if any feature is enabled.
   */
  bool
  isLocalControlHeaderEnabled() const;

  /** \brief get whether a specific LocalControlHeader feature is enabled
   *
   *  \param feature The feature.
   *  \returns true if the specified feature is enabled.
   */
  bool
  isLocalControlHeaderEnabled(LocalControlFeature feature) const;

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

public:

  static const size_t LOCAL_CONTROL_FEATURE_MAX = 3; /// upper bound of LocalControlFeature enum
  static const size_t LOCAL_CONTROL_FEATURE_ANY = 0; /// any feature

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& remoteUri, const FaceUri& localUri)
  : Face(remoteUri, localUri, true)
  , m_localControlHeaderFeatures(LocalFace::LOCAL_CONTROL_FEATURE_MAX)
{
}

inline bool
LocalFace::isLocalControlHeaderEnabled() const
{
  return m_localControlHeaderFeatures[LOCAL_CONTROL_FEATURE_ANY];
}

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

inline void
LocalFace::setLocalControlHeaderFeature(LocalControlFeature feature, bool enabled/* = true*/)
{
  BOOST_ASSERT(0 < feature && feature < m_localControlHeaderFeatures.size());

  m_localControlHeaderFeatures[feature] = enabled;

  m_localControlHeaderFeatures[LOCAL_CONTROL_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_FEATURE_NEXT_HOP_FACE_ID));
        }

      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_FEATURE_INCOMING_FACE_ID),
                      false);
}

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

} // namespace nfd

#endif // NFD_DAEMON_FACE_LOCAL_FACE_HPP
