/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2015 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 "util/concepts.hpp"

#include <algorithm>

#include <boost/range/adaptors.hpp>

namespace ndn {

BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Link>));
BOOST_CONCEPT_ASSERT((WireEncodable<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>&) const;

template size_t
Link::encodeContent<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>&) 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)
    {
      throw 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()) {
      throw Error("Unexpected Link Encoding");
    }
    uint32_t preference;
    try {
      preference = static_cast<uint32_t>(readNonNegativeInteger(*val));
    }
    catch (tlv::Error&) {
      throw Error("Missing preference field in Link Encoding");
    }
    ++val;
    if (val == delegation.elements_end()) {
      throw 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) {
    throw 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) {
      throw 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
