/* -*- 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/key-locator.hpp"
#include "ndn-cxx/encoding/block-helpers.hpp"
#include "ndn-cxx/util/string-helper.hpp"

#include <boost/hana/functional/overload.hpp>

namespace ndn {

constexpr size_t MAX_KEY_DIGEST_OCTETS_TO_SHOW = 8;

KeyLocator::KeyLocator() = default;

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

KeyLocator::KeyLocator(const Name& name)
  : m_locator(name)
{
}

template<encoding::Tag TAG>
size_t
KeyLocator::wireEncode(EncodingImpl<TAG>& encoder) const
{
  // KeyLocator = KEY-LOCATOR-TYPE TLV-LENGTH (Name / KeyDigest)
  // KeyDigest = KEY-DIGEST-TYPE TLV-LENGTH *OCTET

  size_t totalLength = 0;

  std::visit(boost::hana::overload(
    []  (std::monostate)      {}, // nothing to encode, TLV-VALUE is empty
    [&] (const Name& name)    { totalLength += name.wireEncode(encoder); },
    [&] (const Block& digest) { totalLength += prependBlock(encoder, digest); },
    []  (uint32_t type)       { NDN_THROW(Error("Unsupported KeyLocator type " + to_string(type))); }),
    m_locator);

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

NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(KeyLocator);

const Block&
KeyLocator::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
KeyLocator::wireDecode(const Block& wire)
{
  if (wire.type() != tlv::KeyLocator)
    NDN_THROW(Error("KeyLocator", wire.type()));

  clear();
  m_wire = wire;
  m_wire.parse();

  auto element = m_wire.elements_begin();
  if (element == m_wire.elements().end()) {
    return;
  }

  switch (element->type()) {
  case tlv::Name:
    m_locator.emplace<Name>(*element);
    break;
  case tlv::KeyDigest:
    m_locator.emplace<Block>(*element);
    break;
  default:
    m_locator = element->type();
    break;
  }
}

uint32_t
KeyLocator::getType() const
{
  switch (m_locator.index()) {
  case 0:
    return tlv::Invalid;
  case 1:
    return tlv::Name;
  case 2:
    return tlv::KeyDigest;
  case 3:
    return std::get<uint32_t>(m_locator);
  default:
    NDN_CXX_UNREACHABLE;
  }
}

KeyLocator&
KeyLocator::clear()
{
  m_locator = std::monostate{};
  m_wire.reset();
  return *this;
}

const Name&
KeyLocator::getName() const
{
  try {
    return std::get<Name>(m_locator);
  }
  catch (const std::bad_variant_access&) {
    NDN_THROW(Error("KeyLocator does not contain a Name"));
  }
}

KeyLocator&
KeyLocator::setName(const Name& name)
{
  m_locator = name;
  m_wire.reset();
  return *this;
}

const Block&
KeyLocator::getKeyDigest() const
{
  try {
    return std::get<Block>(m_locator);
  }
  catch (const std::bad_variant_access&) {
    NDN_THROW(Error("KeyLocator does not contain a KeyDigest"));
  }
}

KeyLocator&
KeyLocator::setKeyDigest(const Block& keyDigest)
{
  if (keyDigest.type() != tlv::KeyDigest) {
    NDN_THROW(std::invalid_argument("Invalid KeyDigest block of type " + to_string(keyDigest.type())));
  }
  m_locator = keyDigest;
  m_wire.reset();
  return *this;
}

KeyLocator&
KeyLocator::setKeyDigest(const ConstBufferPtr& keyDigest)
{
  BOOST_ASSERT(keyDigest != nullptr);
  m_locator = makeBinaryBlock(tlv::KeyDigest, *keyDigest);
  m_wire.reset();
  return *this;
}

void
KeyLocator::print(std::ostream& os) const
{
  std::visit(boost::hana::overload(
    [&] (std::monostate) {
      os << "None";
    },
    [&] (const Name& name) {
      os << "Name=" << name;
    },
    [&] (const Block& digest) {
      os << "KeyDigest=";
      printHex(os, {digest.value(), std::min(digest.value_size(), MAX_KEY_DIGEST_OCTETS_TO_SHOW)});
      if (digest.value_size() > MAX_KEY_DIGEST_OCTETS_TO_SHOW) {
        os << "...";
      }
    },
    [&] (uint32_t type) {
      os << "Unknown(" << type << ")";
    }),
    m_locator);
}

} // namespace ndn
