/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  Regents of the University of California.
 *
 * This file is part of NDN repo-ng (Next generation of NDN repository).
 * See AUTHORS.md for complete list of repo-ng authors and contributors.
 *
 * repo-ng 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.
 *
 * repo-ng 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
 * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef REPO_REPO_COMMAND_PARAMETER_HPP
#define REPO_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 // REPO_REPO_COMMAND_PARAMETER_HPP
