/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * See COPYING for copyright and distribution information.
 */

#ifndef REPO_HELPERS_REPO_COMMAND_PARAMETER_HPP
#define REPO_HELPERS_REPO_COMMAND_PARAMETER_HPP

#include <ndn-cxx/encoding/encoding-buffer.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/selectors.hpp>
#include "repo-tlv.hpp"

namespace repo {

using ndn::Name;
using ndn::Block;
using ndn::EncodingImpl;
using ndn::Selectors;
using ndn::EncodingEstimator;
using ndn::EncodingBuffer;

/**
* @brief Class defining abstraction of parameter of command for NDN Repo Protocol
* @sa link http://redmine.named-data.net/projects/repo-ng/wiki/Repo_Protocol_Specification#RepoCommandParameter
**/

class RepoCommandParameter
{
public:
  class Error : public ndn::Tlv::Error
  {
  public:
    explicit
    Error(const std::string& what)
      : ndn::Tlv::Error(what)
    {
    }
  };

  RepoCommandParameter()
    : m_hasName(false)
    , m_hasStartBlockId(false)
    , m_hasEndBlockId(false)
    , m_hasProcessId(false)
  {
  }

  explicit
  RepoCommandParameter(const Block& block)
  {
    wireDecode(block);
  }

  const Name&
  getName() const
  {
    return m_name;
  }

  RepoCommandParameter&
  setName(const Name& name)
  {
    m_name = name;
    m_hasName = true;
    m_wire.reset();
    return *this;
  }

  bool
  hasName() const
  {
    return m_hasName;
  }

  const Selectors&
  getSelectors() const
  {
    return m_selectors;
  }

  RepoCommandParameter&
  setSelectors(const Selectors& selectors)
  {
    m_selectors = selectors;
    m_wire.reset();
    return *this;
  }

  bool
  hasSelectors() const
  {
    return !m_selectors.empty();
  }

  uint64_t
  getStartBlockId() const
  {
    assert(hasStartBlockId());
    return m_startBlockId;
  }

  RepoCommandParameter&
  setStartBlockId(uint64_t startBlockId)
  {
    m_startBlockId  = startBlockId;
    m_hasStartBlockId = true;
    m_wire.reset();
    return *this;
  }

  bool
  hasStartBlockId() const
  {
    return m_hasStartBlockId;
  }

  uint64_t
  getEndBlockId() const
  {
    assert(hasEndBlockId());
    return m_endBlockId;
  }

  RepoCommandParameter&
  setEndBlockId(uint64_t endBlockId)
  {
    m_endBlockId  = endBlockId;
    m_hasEndBlockId = true;
    m_wire.reset();
    return *this;
  }

  bool
  hasEndBlockId() const
  {
    return m_hasEndBlockId;
  }

  uint64_t
  getProcessId() const
  {
    assert(hasProcessId());
    return m_processId;
  }

  bool
  hasProcessId() const
  {
    return m_hasProcessId;
  }

  RepoCommandParameter&
  setProcessId(uint64_t processId)
  {
    m_processId = processId;
    m_hasProcessId = true;
    m_wire.reset();
    return *this;
  }

  template<bool T>
  size_t
  wireEncode(EncodingImpl<T>& block) const;

  const Block&
  wireEncode() const;

  void
  wireDecode(const Block& wire);

private:

  Name m_name;
  Selectors m_selectors;
  uint64_t m_startBlockId;
  uint64_t m_endBlockId;
  uint64_t m_processId;

  bool m_hasName;
  bool m_hasStartBlockId;
  bool m_hasEndBlockId;
  bool m_hasProcessId;

  mutable Block m_wire;
};

template<bool T>
inline size_t
RepoCommandParameter::wireEncode(EncodingImpl<T>& encoder) const
{
  size_t totalLength = 0;
  size_t variableLength = 0;

  if (m_hasProcessId) {
    variableLength = encoder.prependNonNegativeInteger(m_processId);
    totalLength += variableLength;
    totalLength += encoder.prependVarNumber(variableLength);
    totalLength += encoder.prependVarNumber(tlv::ProcessId);
  }

  if (m_hasEndBlockId) {
    variableLength = encoder.prependNonNegativeInteger(m_endBlockId);
    totalLength += variableLength;
    totalLength += encoder.prependVarNumber(variableLength);
    totalLength += encoder.prependVarNumber(tlv::EndBlockId);
  }

  if (m_hasStartBlockId) {
    variableLength = encoder.prependNonNegativeInteger(m_startBlockId);
    totalLength += variableLength;
    totalLength += encoder.prependVarNumber(variableLength);
    totalLength += encoder.prependVarNumber(tlv::StartBlockId);
  }

  if (!getSelectors().empty()) {
    totalLength += getSelectors().wireEncode(encoder);
  }

  if (m_hasName) {
    totalLength += getName().wireEncode(encoder);
  }

  totalLength += encoder.prependVarNumber(totalLength);
  totalLength += encoder.prependVarNumber(tlv::RepoCommandParameter);
  return totalLength;
}

inline const Block&
RepoCommandParameter::wireEncode() const
{
  if (m_wire.hasWire())
    return m_wire;

  EncodingEstimator estimator;
  size_t estimatedSize = wireEncode(estimator);

  EncodingBuffer buffer(estimatedSize, 0);
  wireEncode(buffer);

  m_wire = buffer.block();
  return m_wire;
}

inline void
RepoCommandParameter::wireDecode(const Block& wire)
{
  m_hasName = false;
  m_hasStartBlockId = false;
  m_hasEndBlockId = false;
  m_hasProcessId = false;

  m_wire = wire;

  m_wire.parse();

  if (m_wire.type() != tlv::RepoCommandParameter)
    throw Error("Requested decoding of RepoCommandParameter, but Block is of different type");

  // Name
  Block::element_const_iterator val = m_wire.find(tlv::Name);
  if (val != m_wire.elements_end())
  {
    m_hasName = true;
    m_name.wireDecode(m_wire.get(tlv::Name));
  }

  // Selectors
  val = m_wire.find(tlv::Selectors);
  if (val != m_wire.elements_end())
  {
    m_selectors.wireDecode(*val);
  }
  else
    m_selectors = Selectors();

  // StartBlockId
  val = m_wire.find(tlv::StartBlockId);
  if (val != m_wire.elements_end())
  {
    m_hasStartBlockId = true;
    m_startBlockId = readNonNegativeInteger(*val);
  }

  // EndBlockId
  val = m_wire.find(tlv::EndBlockId);
  if (val != m_wire.elements_end())
  {
    m_hasEndBlockId = true;
    m_endBlockId = readNonNegativeInteger(*val);
  }

  // ProcessId
  val = m_wire.find(tlv::ProcessId);
  if (val != m_wire.elements_end())
  {
    m_hasProcessId = true;
    m_processId = readNonNegativeInteger(*val);
  }

}

inline std::ostream&
operator<<(std::ostream& os, const RepoCommandParameter& repoCommandParameter)
{
  os << "RepoCommandParameter(";

  // Name
  if (repoCommandParameter.hasName()) {
    os << " Name: " << repoCommandParameter.getName();
  }
  if (repoCommandParameter.hasStartBlockId()) {
  // StartBlockId
    os << " StartBlockId: " << repoCommandParameter.getStartBlockId();
  }
  // EndBlockId
  if (repoCommandParameter.hasEndBlockId()) {
    os << " EndBlockId: " << repoCommandParameter.getEndBlockId();
  }
  //ProcessId
  if (repoCommandParameter.hasProcessId()) {
    os << " ProcessId: " << repoCommandParameter.getProcessId();
  }
  os << " )";
  return os;
}

} //namespace repo

#endif
