/* -*- 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-cxx/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 &&
               static_cast<size_t>(feature) < m_localControlHeaderFeatures.size());
  return m_localControlHeaderFeatures[feature];
}

inline void
LocalFace::setLocalControlHeaderFeature(LocalControlFeature feature, bool enabled/* = true*/)
{
  BOOST_ASSERT(0 < feature &&
               static_cast<size_t>(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)
{
  try {
    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->emitSignal(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->emitSignal(onReceiveData, *d);
      }
    else
      return false;

    return true;
  }
  catch (tlv::Error&) {
    return false;
  }
}

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
