/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2018 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "meta-info.hpp"
#include "encoding/block-helpers.hpp"
#include "encoding/encoding-buffer.hpp"

namespace ndn {

BOOST_CONCEPT_ASSERT((boost::EqualityComparable<MetaInfo>));
BOOST_CONCEPT_ASSERT((WireEncodable<MetaInfo>));
BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<MetaInfo>));
BOOST_CONCEPT_ASSERT((WireDecodable<MetaInfo>));
static_assert(std::is_base_of<tlv::Error, MetaInfo::Error>::value,
              "MetaInfo::Error must inherit from tlv::Error");

MetaInfo::MetaInfo()
  : m_type(tlv::ContentType_Blob)
  , m_freshnessPeriod(DEFAULT_FRESHNESS_PERIOD)
{
}

MetaInfo::MetaInfo(const Block& block)
{
  wireDecode(block);
}

MetaInfo&
MetaInfo::setType(uint32_t type)
{
  m_wire.reset();
  m_type = type;
  return *this;
}

MetaInfo&
MetaInfo::setFreshnessPeriod(time::milliseconds freshnessPeriod)
{
  if (freshnessPeriod < time::milliseconds::zero()) {
    BOOST_THROW_EXCEPTION(std::invalid_argument("FreshnessPeriod must be >= 0"));
  }
  m_wire.reset();
  m_freshnessPeriod = freshnessPeriod;
  return *this;
}

MetaInfo&
MetaInfo::setFinalBlock(optional<name::Component> finalBlockId)
{
  m_wire.reset();
  m_finalBlockId = std::move(finalBlockId);
  return *this;
}

const std::list<Block>&
MetaInfo::getAppMetaInfo() const
{
  return m_appMetaInfo;
}

MetaInfo&
MetaInfo::setAppMetaInfo(const std::list<Block>& info)
{
  for (const auto& block : info) {
    if (block.type() < 128 || block.type() > 252)
      BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range [128, 252]"));
  }

  m_wire.reset();
  m_appMetaInfo = info;
  return *this;
}

MetaInfo&
MetaInfo::addAppMetaInfo(const Block& block)
{
  if (!(128 <= block.type() && block.type() <= 252))
    BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range "
                                "[128, 252]"));

  m_wire.reset();
  m_appMetaInfo.push_back(block);
  return *this;
}

bool
MetaInfo::removeAppMetaInfo(uint32_t tlvType)
{
  for (auto it = m_appMetaInfo.begin(); it != m_appMetaInfo.end(); ++it) {
    if (it->type() == tlvType) {
      m_wire.reset();
      m_appMetaInfo.erase(it);
      return true;
    }
  }
  return false;
}

const Block*
MetaInfo::findAppMetaInfo(uint32_t tlvType) const
{
  auto it = std::find_if(m_appMetaInfo.begin(), m_appMetaInfo.end(),
                         [=] (const Block& b) { return b.type() == tlvType; });
  return it != m_appMetaInfo.end() ? &*it : nullptr;
}

template<encoding::Tag TAG>
size_t
MetaInfo::wireEncode(EncodingImpl<TAG>& encoder) const
{
  // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
  //                ContentType?
  //                FreshnessPeriod?
  //                FinalBlockId?
  //                AppMetaInfo*

  size_t totalLength = 0;

  for (auto it = m_appMetaInfo.rbegin(); it != m_appMetaInfo.rend(); ++it) {
    totalLength += encoder.prependBlock(*it);
  }

  // FinalBlockId
  if (m_finalBlockId) {
    totalLength += prependNestedBlock(encoder, tlv::FinalBlockId, *m_finalBlockId);
  }

  // FreshnessPeriod
  if (m_freshnessPeriod != DEFAULT_FRESHNESS_PERIOD) {
    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod,
                                                  static_cast<uint64_t>(m_freshnessPeriod.count()));
  }

  // ContentType
  if (m_type != tlv::ContentType_Blob) {
    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::ContentType, m_type);
  }

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

NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(MetaInfo);

const Block&
MetaInfo::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;
}

void
MetaInfo::wireDecode(const Block& wire)
{
  m_wire = wire;
  m_wire.parse();

  // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
  //                ContentType?
  //                FreshnessPeriod?
  //                FinalBlockId?
  //                AppMetaInfo*

  auto val = m_wire.elements_begin();

  // ContentType
  if (val != m_wire.elements_end() && val->type() == tlv::ContentType) {
    m_type = readNonNegativeIntegerAs<uint32_t>(*val);
    ++val;
  }
  else {
    m_type = tlv::ContentType_Blob;
  }

  // FreshnessPeriod
  if (val != m_wire.elements_end() && val->type() == tlv::FreshnessPeriod) {
    m_freshnessPeriod = time::milliseconds(readNonNegativeInteger(*val));
    ++val;
  }
  else {
    m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD;
  }

  // FinalBlockId
  if (val != m_wire.elements_end() && val->type() == tlv::FinalBlockId) {
    m_finalBlockId.emplace(val->blockFromValue());
    ++val;
  }
  else {
    m_finalBlockId = nullopt;
  }

  // AppMetaInfo (if any)
  for (; val != m_wire.elements().end(); ++val) {
    m_appMetaInfo.push_back(*val);
  }
}

std::ostream&
operator<<(std::ostream& os, const MetaInfo& info)
{
  // ContentType
  os << "ContentType: " << info.getType();

  // FreshnessPeriod
  if (info.getFreshnessPeriod() > 0_ms) {
    os << ", FreshnessPeriod: " << info.getFreshnessPeriod();
  }

  // FinalBlockId
  if (info.getFinalBlock()) {
    os << ", FinalBlockId: ";
    info.getFinalBlock()->toUri(os);
  }

  // App-defined MetaInfo items
  for (const auto& block : info.getAppMetaInfo()) {
    os << ", AppMetaInfoTlvType: " << block.type();
  }

  return os;
}

} // namespace ndn
