/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_FORWARDING_FLAGS_HPP
#define NDN_FORWARDING_FLAGS_HPP

#include "../encoding/block.hpp"
#include "../encoding/tlv-ndnd.hpp"

namespace ndn {
namespace ndnd {

/**
 * A ForwardingFlags object holds the flags which specify how the forwarding daemon should forward an interest for
 * a registered prefix.  We use a separate ForwardingFlags object to retain future compatibility if the daemon forwarding
 * bits are changed, amended or deprecated.
 */
class ForwardingFlags {
public:
  /**
   * Create a new ForwardingFlags with "active" and "childInherit" set and all other flags cleared.
   */
  ForwardingFlags()
    : active_(true)
    , childInherit_(true)
    , advertise_(false)
    , last_(false)
    , capture_(false)
    , local_(false)
    , tap_(false)
    , captureOk_(false)
  {
  }

  /**
   * @brief Create from wire encoding
   */
  explicit
  ForwardingFlags(const Block& wire)
  {
    wireDecode(wire);
  }

  /**
   * Get the value of the "active" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getActive() const { return active_; }

  /**
   * Get the value of the "childInherit" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getChildInherit() const { return childInherit_; }

  /**
   * Get the value of the "advertise" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getAdvertise() const { return advertise_; }

  /**
   * Get the value of the "last" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getLast() const { return last_; }

  /**
   * Get the value of the "capture" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getCapture() const { return capture_; }

  /**
   * Get the value of the "local" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getLocal() const { return local_; }

  /**
   * Get the value of the "tap" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getTap() const { return tap_; }

  /**
   * Get the value of the "captureOk" flag.
   * @return true if the flag is set, false if it is cleared.
   */
  bool getCaptureOk() const { return captureOk_; }

  /**
   * Set the value of the "active" flag
   * @param active true to set the flag, false to clear it.
   */
  void setActive(bool active) { this->active_ = active; wire_.reset(); }

  /**
   * Set the value of the "childInherit" flag
   * @param childInherit true to set the flag, false to clear it.
   */
  void setChildInherit(bool childInherit) { this->childInherit_ = childInherit; wire_.reset(); }

  /**
   * Set the value of the "advertise" flag
   * @param advertise true to set the flag, false to clear it.
   */
  void setAdvertise(bool advertise) { this->advertise_ = advertise; wire_.reset(); }

  /**
   * Set the value of the "last" flag
   * @param last true to set the flag, false to clear it.
   */
  void setLast(bool last) { this->last_ = last; wire_.reset(); }

  /**
   * Set the value of the "capture" flag
   * @param capture true to set the flag, false to clear it.
   */
  void setCapture(bool capture) { this->capture_ = capture; wire_.reset(); }

  /**
   * Set the value of the "local" flag
   * @param local true to set the flag, false to clear it.
   */
  void setLocal(bool local) { this->local_ = local; wire_.reset(); }

  /**
   * Set the value of the "tap" flag
   * @param tap true to set the flag, false to clear it.
   */
  void setTap(bool tap) { this->tap_ = tap; wire_.reset(); }

  /**
   * Set the value of the "captureOk" flag
   * @param captureOk true to set the flag, false to clear it.
   */
  void setCaptureOk(bool captureOk) { this->captureOk_ = captureOk; wire_.reset(); }

  inline const Block&
  wireEncode() const;

  inline void
  wireDecode(const Block& block);

private:
  bool active_;
  bool childInherit_;
  bool advertise_;
  bool last_;
  bool capture_;
  bool local_;
  bool tap_;
  bool captureOk_;

  mutable Block wire_;
};

inline const Block&
ForwardingFlags::wireEncode() const
{
  if (wire_.hasWire())
    return wire_;

  uint32_t result = 0;
  if (active_)
    result |= tlv::ndnd::FORW_ACTIVE;
  if (childInherit_)
    result |= tlv::ndnd::FORW_CHILD_INHERIT;
  if (advertise_)
    result |= tlv::ndnd::FORW_ADVERTISE;
  if (last_)
    result |= tlv::ndnd::FORW_LAST;
  if (capture_)
    result |= tlv::ndnd::FORW_CAPTURE;
  if (local_)
    result |= tlv::ndnd::FORW_LOCAL;
  if (tap_)
    result |= tlv::ndnd::FORW_TAP;
  if (captureOk_)
    result |= tlv::ndnd::FORW_CAPTURE_OK;

  wire_ = nonNegativeIntegerBlock(tlv::ndnd::ForwardingFlags, result);

  return wire_;
}

inline void
ForwardingFlags::wireDecode(const Block& wire)
{
  wire_ = wire;

  uint32_t flags = readNonNegativeInteger(wire_);

  active_       = (flags & tlv::ndnd::FORW_ACTIVE)        ? true : false;
  childInherit_ = (flags & tlv::ndnd::FORW_CHILD_INHERIT) ? true : false;
  advertise_    = (flags & tlv::ndnd::FORW_ADVERTISE)     ? true : false;
  last_         = (flags & tlv::ndnd::FORW_LAST)          ? true : false;
  capture_      = (flags & tlv::ndnd::FORW_CAPTURE)       ? true : false;
  local_        = (flags & tlv::ndnd::FORW_LOCAL)         ? true : false;
  tap_          = (flags & tlv::ndnd::FORW_TAP)           ? true : false;
  captureOk_    = (flags & tlv::ndnd::FORW_CAPTURE_OK)    ? true : false;
}

inline std::ostream&
operator << (std::ostream& os, const ForwardingFlags& flags)
{
  if (flags.getActive())
    os << "ACTIVE ";
  if (flags.getChildInherit())
    os << "CHILE_INHERIT ";
  if (flags.getAdvertise())
    os << "ADVERTISE ";
  if (flags.getLast())
    os << "LAST ";
  if (flags.getCapture())
    os << "CAPTURE ";
  if (flags.getLocal())
    os << "LOCAL ";
  if (flags.getTap())
    os << "TAP ";
  if (flags.getCaptureOk())
    os << "CAPTURE_OK ";

  return os;
}

} // namespace ndnd
} // namespace ndn

#endif
