/* -*- 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_FACE_LOCAL_FACE_HPP
#define NFD_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_FACE_LOCAL_FACE_HPP
