/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2017, 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 "repo-tlv.hpp"

#include <ndn-cxx/encoding/encoding-buffer.hpp>
#include <ndn-cxx/encoding/block-helpers.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/selectors.hpp>

namespace repo {

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

/**
* @brief Class defining abstraction of parameter of command for NDN Repo Protocol
* @sa link https://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)
    , m_hasMaxInterestNum(false)
    , m_hasWatchTimeout(false)
    , m_hasInterestLifetime(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;
  }

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

  bool
  hasProcessId() const
  {
    return m_hasProcessId;
  }

  uint64_t
  getMaxInterestNum() const
  {
    assert(hasMaxInterestNum());
    return m_maxInterestNum;
  }

  RepoCommandParameter&
  setMaxInterestNum(uint64_t maxInterestNum)
  {
    m_maxInterestNum = maxInterestNum;
    m_hasMaxInterestNum = true;
    m_wire.reset();
    return *this;
  }

  bool
  hasMaxInterestNum() const
  {
    return m_hasMaxInterestNum;
  }

  milliseconds
  getWatchTimeout() const
  {
    assert(hasWatchTimeout());
    return m_watchTimeout;
  }

  RepoCommandParameter&
  setWatchTimeout(milliseconds watchTimeout)
  {
    m_watchTimeout = watchTimeout;
    m_hasWatchTimeout = true;
    m_wire.reset();
    return *this;
  }

  bool
  hasWatchTimeout() const
  {
    return m_hasWatchTimeout;
  }

  milliseconds
  getInterestLifetime() const
  {
    assert(hasInterestLifetime());
    return m_interestLifetime;
  }

  RepoCommandParameter&
  setInterestLifetime(milliseconds interestLifetime)
  {
    m_interestLifetime = interestLifetime;
    m_hasInterestLifetime = true;
    m_wire.reset();
    return *this;
  }

  bool
  hasInterestLifetime() const
  {
    return m_hasInterestLifetime;
  }

  template<ndn::encoding::Tag 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;
  uint64_t m_maxInterestNum;
  milliseconds m_watchTimeout;
  milliseconds m_interestLifetime;

  bool m_hasName;
  bool m_hasStartBlockId;
  bool m_hasEndBlockId;
  bool m_hasProcessId;
  bool m_hasMaxInterestNum;
  bool m_hasWatchTimeout;
  bool m_hasInterestLifetime;

  mutable Block m_wire;
};

template<ndn::encoding::Tag 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 (m_hasMaxInterestNum) {
    variableLength = encoder.prependNonNegativeInteger(m_maxInterestNum);
    totalLength += variableLength;
    totalLength += encoder.prependVarNumber(variableLength);
    totalLength += encoder.prependVarNumber(tlv::MaxInterestNum);
  }

  if (m_hasWatchTimeout) {
    variableLength = encoder.prependNonNegativeInteger(m_watchTimeout.count());
    totalLength += variableLength;
    totalLength += encoder.prependVarNumber(variableLength);
    totalLength += encoder.prependVarNumber(tlv::WatchTimeout);
  }

  if (m_hasInterestLifetime) {
    variableLength = encoder.prependNonNegativeInteger(m_interestLifetime.count());
    totalLength += variableLength;
    totalLength += encoder.prependVarNumber(variableLength);
    totalLength += encoder.prependVarNumber(tlv::InterestLifetime);
  }

  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_hasMaxInterestNum = false;
  m_hasWatchTimeout = false;
  m_hasInterestLifetime = false;

  m_wire = wire;

  m_wire.parse();

  if (m_wire.type() != tlv::RepoCommandParameter)
    BOOST_THROW_EXCEPTION(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);
  }

  // MaxInterestNum
  val = m_wire.find(tlv::MaxInterestNum);
  if (val != m_wire.elements_end())
  {
    m_hasMaxInterestNum = true;
    m_maxInterestNum = readNonNegativeInteger(*val);
  }

  // WatchTimeout
  val = m_wire.find(tlv::WatchTimeout);
  if (val != m_wire.elements_end())
  {
    m_hasWatchTimeout = true;
    m_watchTimeout = milliseconds(readNonNegativeInteger(*val));
  }

  // InterestLiftTime
  val = m_wire.find(tlv::InterestLifetime);
  if (val != m_wire.elements_end())
  {
    m_hasInterestLifetime = true;
    m_interestLifetime = milliseconds(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();
  }
  // MaxInterestNum
  if (repoCommandParameter.hasMaxInterestNum()) {
    os << " MaxInterestNum: " << repoCommandParameter.getMaxInterestNum();
  }
  // WatchTimeout
  if (repoCommandParameter.hasProcessId()) {
    os << " WatchTimeout: " << repoCommandParameter.getWatchTimeout();
  }
  // InterestLifetime
  if (repoCommandParameter.hasProcessId()) {
    os << " InterestLifetime: " << repoCommandParameter.getInterestLifetime();
  }
  os << " )";
  return os;
}

} // namespace repo

#endif // REPO_REPO_COMMAND_PARAMETER_HPP
