/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2023 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 "ndn-cxx/data.hpp"
#include "ndn-cxx/util/sha256.hpp"

namespace ndn {

Data::Data(const Name& name)
  : m_name(name)
{
}

Data::Data(const Block& wire)
{
  wireDecode(wire);
}

template<encoding::Tag TAG>
size_t
Data::wireEncode(EncodingImpl<TAG>& encoder, bool wantUnsignedPortionOnly) const
{
  // Data = DATA-TYPE TLV-LENGTH
  //          Name
  //          [MetaInfo]
  //          [Content]
  //          SignatureInfo
  //          SignatureValue
  // (elements are encoded in reverse order)

  size_t totalLength = 0;

  // SignatureValue
  if (!wantUnsignedPortionOnly) {
    if (!m_signatureInfo) {
      NDN_THROW(Error("Requested wire format, but Data has not been signed"));
    }
    totalLength += prependBlock(encoder, m_signatureValue);
  }

  // SignatureInfo
  totalLength += m_signatureInfo.wireEncode(encoder, SignatureInfo::Type::Data);

  // Content
  if (hasContent()) {
    totalLength += prependBlock(encoder, m_content);
  }

  // MetaInfo
  totalLength += m_metaInfo.wireEncode(encoder);

  // Name
  totalLength += m_name.wireEncode(encoder);

  if (!wantUnsignedPortionOnly) {
    totalLength += encoder.prependVarNumber(totalLength);
    totalLength += encoder.prependVarNumber(tlv::Data);
  }
  return totalLength;
}

template size_t
Data::wireEncode<encoding::EncoderTag>(EncodingBuffer&, bool) const;

template size_t
Data::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, bool) const;

const Block&
Data::wireEncode(EncodingBuffer& encoder, span<const uint8_t> signature) const
{
  size_t totalLength = encoder.size();
  totalLength += encoder.appendVarNumber(tlv::SignatureValue);
  totalLength += encoder.appendVarNumber(signature.size());
  totalLength += encoder.appendBytes(signature);

  encoder.prependVarNumber(totalLength);
  encoder.prependVarNumber(tlv::Data);

  const_cast<Data*>(this)->wireDecode(encoder.block());
  return m_wire;
}

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

  EncodingEstimator estimator;
  size_t estimatedSize = wireEncode(estimator);

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

  const_cast<Data*>(this)->wireDecode(buffer.block());
  return m_wire;
}

void
Data::wireDecode(const Block& wire)
{
  if (wire.type() != tlv::Data) {
    NDN_THROW(Error("Data", wire.type()));
  }
  m_wire = wire;
  m_wire.parse();

  // Data = DATA-TYPE TLV-LENGTH
  //          Name
  //          [MetaInfo]
  //          [Content]
  //          SignatureInfo
  //          SignatureValue

  auto element = m_wire.elements_begin();
  if (element == m_wire.elements_end() || element->type() != tlv::Name) {
    NDN_THROW(Error("Name element is missing or out of order"));
  }
  m_name.wireDecode(*element);

  m_metaInfo = {};
  m_content = {};
  m_signatureInfo = {};
  m_signatureValue = {};
  m_fullName.clear();

  int lastElement = 1; // last recognized element index, in spec order
  for (++element; element != m_wire.elements_end(); ++element) {
    switch (element->type()) {
      case tlv::MetaInfo: {
        if (lastElement >= 2) {
          NDN_THROW(Error("MetaInfo element is out of order"));
        }
        m_metaInfo.wireDecode(*element);
        lastElement = 2;
        break;
      }
      case tlv::Content: {
        if (lastElement >= 3) {
          NDN_THROW(Error("Content element is out of order"));
        }
        m_content = *element;
        lastElement = 3;
        break;
      }
      case tlv::SignatureInfo: {
        if (lastElement >= 4) {
          NDN_THROW(Error("SignatureInfo element is out of order"));
        }
        m_signatureInfo.wireDecode(*element);
        lastElement = 4;
        break;
      }
      case tlv::SignatureValue: {
        if (lastElement >= 5) {
          NDN_THROW(Error("SignatureValue element is out of order"));
        }
        m_signatureValue = *element;
        lastElement = 5;
        break;
      }
      default: { // unrecognized element
        // if the TLV-TYPE is critical, abort decoding
        if (tlv::isCriticalType(element->type())) {
          NDN_THROW(Error("Unrecognized element of critical type " + to_string(element->type())));
        }
        // otherwise, ignore it
        break;
      }
    }
  }

  if (!m_signatureInfo) {
    NDN_THROW(Error("SignatureInfo element is missing"));
  }
  if (!m_signatureValue.isValid()) {
    NDN_THROW(Error("SignatureValue element is missing"));
  }
}

const Name&
Data::getFullName() const
{
  if (m_fullName.empty()) {
    if (!m_wire.hasWire()) {
      NDN_THROW(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
    }
    m_fullName = m_name;
    m_fullName.appendImplicitSha256Digest(util::Sha256::computeDigest(m_wire));
  }

  return m_fullName;
}

void
Data::resetWire()
{
  m_wire.reset();
  m_fullName.clear();
}

Data&
Data::setName(const Name& name)
{
  if (name != m_name) {
    m_name = name;
    resetWire();
  }
  return *this;
}

Data&
Data::setMetaInfo(const MetaInfo& metaInfo)
{
  m_metaInfo = metaInfo;
  resetWire();
  return *this;
}

Data&
Data::setContent(const Block& block)
{
  if (!block.isValid()) {
    NDN_THROW(std::invalid_argument("Content block must be valid"));
  }

  if (block.type() == tlv::Content) {
    m_content = block;
  }
  else {
    m_content = Block(tlv::Content, block);
  }
  m_content.encode();
  resetWire();
  return *this;
}

Data&
Data::setContent(span<const uint8_t> value)
{
  m_content = makeBinaryBlock(tlv::Content, value);
  resetWire();
  return *this;
}

Data&
Data::setContent(std::string_view value)
{
  m_content = makeStringBlock(tlv::Content, value);
  resetWire();
  return *this;
}

Data&
Data::setContent(ConstBufferPtr value)
{
  if (!value) {
    NDN_THROW(std::invalid_argument("Content buffer cannot be null"));
  }

  m_content = Block(tlv::Content, std::move(value));
  resetWire();
  return *this;
}

Data&
Data::unsetContent()
{
  if (m_content.isValid()) {
    m_content = {};
    resetWire();
  }
  return *this;
}

Data&
Data::setSignatureInfo(const SignatureInfo& info)
{
  m_signatureInfo = info;
  resetWire();
  return *this;
}

Data&
Data::setSignatureValue(span<const uint8_t> value)
{
  m_signatureValue = makeBinaryBlock(tlv::SignatureValue, value);
  resetWire();
  return *this;
}

Data&
Data::setSignatureValue(ConstBufferPtr value)
{
  if (!value) {
    NDN_THROW(std::invalid_argument("SignatureValue buffer cannot be null"));
  }

  m_signatureValue = Block(tlv::SignatureValue, std::move(value));
  resetWire();
  return *this;
}

InputBuffers
Data::extractSignedRanges() const
{
  InputBuffers bufs;
  bufs.reserve(1); // One range containing data value up to, but not including, SignatureValue

  wireEncode();
  auto lastSignedIt = std::prev(m_wire.find(tlv::SignatureValue));
  // Note: we assume that both iterators point to the same underlying buffer
  bufs.emplace_back(m_wire.value_begin(), lastSignedIt->end());

  return bufs;
}

Data&
Data::setContentType(uint32_t type)
{
  if (type != m_metaInfo.getType()) {
    m_metaInfo.setType(type);
    resetWire();
  }
  return *this;
}

Data&
Data::setFreshnessPeriod(time::milliseconds freshnessPeriod)
{
  if (freshnessPeriod != m_metaInfo.getFreshnessPeriod()) {
    m_metaInfo.setFreshnessPeriod(freshnessPeriod);
    resetWire();
  }
  return *this;
}

Data&
Data::setFinalBlock(std::optional<name::Component> finalBlockId)
{
  if (finalBlockId != m_metaInfo.getFinalBlock()) {
    m_metaInfo.setFinalBlock(std::move(finalBlockId));
    resetWire();
  }
  return *this;
}

bool
operator==(const Data& lhs, const Data& rhs)
{
  return lhs.getName() == rhs.getName() &&
         lhs.getMetaInfo().wireEncode() == rhs.getMetaInfo().wireEncode() &&
         lhs.getContent() == rhs.getContent() &&
         lhs.getSignatureInfo() == rhs.getSignatureInfo() &&
         lhs.getSignatureValue() == rhs.getSignatureValue();
}

std::ostream&
operator<<(std::ostream& os, const Data& data)
{
  os << "Name: " << data.getName() << "\n"
     << "MetaInfo: [" << data.getMetaInfo() << "]\n";

  if (data.hasContent()) {
    os << "Content: [" << data.getContent().value_size() << " bytes]\n";
  }

  os << "Signature: [type: " << static_cast<tlv::SignatureTypeValue>(data.getSignatureType())
     << ", length: "<< data.getSignatureValue().value_size() << "]\n";

  return os;
}

} // namespace ndn
