/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 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 "link.hpp"
#include "interest.hpp"
#include "encoding/block-helpers.hpp"
#include "util/crypto.hpp"
#include "security/key-chain.hpp"

#include <boost/range/adaptor/reversed.hpp>

namespace ndn {

BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Link>));
BOOST_CONCEPT_ASSERT((WireEncodable<Link>));
BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Link>));
BOOST_CONCEPT_ASSERT((WireDecodable<Link>));
static_assert(std::is_base_of<Data::Error, Link::Error>::value,
              "Link::Error should inherit from Data::Error");

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

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

Link::Link(const Name& name, std::initializer_list<std::pair<uint32_t, Name>> links)
  : Data(name)
{
  m_delegations.insert(links);
  encodeContent();
}

void
Link::addDelegation(uint32_t preference, const Name& name)
{
  this->removeDelegationNoEncode(name);
  m_delegations.insert({preference, name});
  encodeContent();
}

bool
Link::removeDelegation(const Name& name)
{
  bool hasRemovedDelegation = this->removeDelegationNoEncode(name);
  if (hasRemovedDelegation) {
    encodeContent();
  }
  return hasRemovedDelegation;
}

const Link::DelegationSet&
Link::getDelegations() const
{
  return m_delegations;
}

template<encoding::Tag TAG>
size_t
Link::encodeContent(EncodingImpl<TAG>& encoder) const
{
  // LinkContent ::= CONTENT-TYPE TLV-LENGTH
  //                    Delegation+

  // Delegation ::= LINK-DELEGATION-TYPE TLV-LENGTH
  //              Preference
  //              Name

  // Preference ::= LINK-PREFERENCE-TYPE TLV-LENGTH
  //       nonNegativeInteger

  size_t totalLength = 0;
  for (const auto& delegation : m_delegations |  boost::adaptors::reversed) {
    size_t delegationLength = 0;
    delegationLength += std::get<1>(delegation).wireEncode(encoder);
    delegationLength += prependNonNegativeIntegerBlock(encoder, tlv::LinkPreference,
                                                       std::get<0>(delegation));
    delegationLength += encoder.prependVarNumber(delegationLength);
    delegationLength += encoder.prependVarNumber(tlv::LinkDelegation);
    totalLength += delegationLength;
  }
  totalLength += encoder.prependVarNumber(totalLength);
  totalLength += encoder.prependVarNumber(tlv::Content);
  return totalLength;
}

template size_t
Link::encodeContent<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;

template size_t
Link::encodeContent<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;

void
Link::encodeContent()
{
  onChanged();

  EncodingEstimator estimator;
  size_t estimatedSize = encodeContent(estimator);

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

  setContentType(tlv::ContentType_Link);
  setContent(buffer.block());
}

void
Link::decodeContent()
{
  // LinkContent ::= CONTENT-TYPE TLV-LENGTH
  //                    Delegation+

  // Delegation ::= LINK-DELEGATION-TYPE TLV-LENGTH
  //              Preference
  //              Name

  // Preference ::= LINK-PREFERENCE-TYPE TLV-LENGTH
  //       nonNegativeInteger

  if (getContentType() != tlv::ContentType_Link)
    {
      BOOST_THROW_EXCEPTION(Error("Expected Content Type Link"));
    }

  const Block& content = getContent();
  content.parse();

  for (auto& delegation : content.elements()) {
    delegation.parse();
    Block::element_const_iterator val = delegation.elements_begin();
    if (val == delegation.elements_end()) {
      BOOST_THROW_EXCEPTION(Error("Unexpected Link Encoding"));
    }
    uint32_t preference;
    try {
      preference = static_cast<uint32_t>(readNonNegativeInteger(*val));
    }
    catch (const tlv::Error&) {
      BOOST_THROW_EXCEPTION(Error("Missing Preference field in Link Encoding"));
    }
    ++val;
    if (val == delegation.elements_end()) {
      BOOST_THROW_EXCEPTION(Error("Missing Name field in Link Encoding"));
    }
    Name name(*val);
    m_delegations.insert({preference, name});
  }
}

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

std::tuple<uint32_t, Name>
Link::getDelegationFromWire(const Block& block, size_t index)
{
  block.parse();
  const Block& contentBlock = block.get(tlv::Content);
  contentBlock.parse();
  const Block& delegationBlock = contentBlock.elements().at(index);
  delegationBlock.parse();
  if (delegationBlock.type() != tlv::LinkDelegation) {
    BOOST_THROW_EXCEPTION(Error("Unexpected TLV-TYPE, expecting LinkDelegation"));
  }
  return std::make_tuple(
    static_cast<uint32_t>(
      readNonNegativeInteger(delegationBlock.get(tlv::LinkPreference))),
    Name(delegationBlock.get(tlv::Name)));
}

ssize_t
Link::findDelegationFromWire(const Block& block, const Name& delegationName)
{
  block.parse();
  const Block& contentBlock = block.get(tlv::Content);
  contentBlock.parse();
  size_t counter = 0;
  for (auto&& delegationBlock : contentBlock.elements()) {
    delegationBlock.parse();
    if (delegationBlock.type() != tlv::LinkDelegation) {
      BOOST_THROW_EXCEPTION(Error("Unexpected TLV-TYPE, expecting LinkDelegation"));
    }
    Name name(delegationBlock.get(tlv::Name));
    if (name == delegationName) {
      return counter;
    }
    ++counter;
  }
  return INVALID_SELECTED_DELEGATION_INDEX;
}

ssize_t
Link::countDelegationsFromWire(const Block& block)
{
  block.parse();
  const Block& contentBlock = block.get(tlv::Content);
  contentBlock.parse();
  return contentBlock.elements_size();
}

bool
Link::removeDelegationNoEncode(const Name& name)
{
  bool hasRemoved = false;
  auto i = m_delegations.begin();
  while (i != m_delegations.end()) {
    if (i->second == name) {
      hasRemoved = true;
      i = m_delegations.erase(i);
    }
    else {
      ++i;
    }
  }
  return hasRemoved;
}

} // namespace ndn
