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

#include "response.hpp"
#include "logger.hpp"

namespace ndn {
namespace ndns {

Response::Response()
  : m_ndnsType(NDNS_RAW)
  , m_freshnessPeriod(DEFAULT_RR_FRESHNESS_PERIOD)
  , m_appContent(makeBinaryBlock(ndn::tlv::Content, reinterpret_cast<const uint8_t*>(0), 0))
{
}

Response::Response(const Name& zone, const name::Component& queryType)
  : m_zone(zone)
  , m_queryType(queryType)
  , m_ndnsType(NDNS_RAW)
  , m_freshnessPeriod(DEFAULT_RR_FRESHNESS_PERIOD)
  , m_appContent(makeBinaryBlock(ndn::tlv::Content, reinterpret_cast<const uint8_t*>(0), 0))
{
}

template<bool T>
inline size_t
Response::wireEncode(EncodingImpl<T>& block) const
{
  if (m_ndnsType == NDNS_RAW) {
    // Raw application content
    return block.prependBlock(m_appContent);
  }

  // Content :: = CONTENT-TYPE TLV-LENGTH
  //              Block*

  size_t totalLength = 0;
  for (std::vector<Block>::const_reverse_iterator iter = m_rrs.rbegin();
       iter != m_rrs.rend(); ++iter) {
    totalLength += block.prependBlock(*iter);
  }

  totalLength += block.prependVarNumber(totalLength);
  totalLength += block.prependVarNumber(::ndn::tlv::Content);

  return totalLength;
}

const Block
Response::wireEncode() const
{
  if (m_ndnsType == NDNS_RAW) {
    return m_appContent;
  }

  EncodingEstimator estimator;
  size_t estimatedSize = wireEncode(estimator);
  EncodingBuffer buffer(estimatedSize, 0);
  wireEncode(buffer);
  return buffer.block();
}

void
Response::wireDecode(const Block& wire)
{
  if (m_ndnsType == NDNS_RAW) {
    m_appContent = wire;
    return;
  }

  wire.parse();

  Block::element_const_iterator iter = wire.elements().begin();
  for (; iter != wire.elements().end(); ++iter) {
    m_rrs.push_back(*iter);
  }
}

bool
Response::fromData(const Name& hint, const Name& zone, const Data& data)
{
  label::MatchResult re;
  if (!matchName(data, hint, zone, re))
    return false;

  m_rrLabel = re.rrLabel;
  m_rrType = re.rrType;
  m_version = re.version;

  m_zone = zone;
  size_t len = zone.size();
  if (!hint.empty())
    len += hint.size() + 1;
  m_queryType = data.getName().get(len);

  MetaInfo info = data.getMetaInfo();

  m_freshnessPeriod = time::duration_cast<time::seconds>(info.getFreshnessPeriod());
  const Block* block = info.findAppMetaInfo(tlv::NdnsType);
  if (block != 0)
    m_ndnsType = static_cast<NdnsType>(readNonNegativeInteger(*block));

  wireDecode(data.getContent());
  return true;
}


shared_ptr<Data>
Response::toData()
{
  Name name;
  name.append(m_zone)
      .append(m_queryType)
      .append(m_rrLabel)
      .append(m_rrType);

  if (m_version.empty()) {
    name.appendVersion();
    m_version = name.get(-1);
  }
  else {
    name.append(m_version);
  }

  shared_ptr<Data> data = make_shared<Data>(name);

  MetaInfo info;
  info.setFreshnessPeriod(m_freshnessPeriod);

  if (m_ndnsType != NDNS_RAW) {
    info.addAppMetaInfo(makeNonNegativeIntegerBlock(ndns::tlv::NdnsType, m_ndnsType));
    data->setContent(this->wireEncode());
  }
  else {
    data->setContent(m_appContent);
  }
  data->setMetaInfo(info);

  return data;
}


Response&
Response::addRr(const Block& rr)
{
  this->m_rrs.push_back(rr);
  return *this;
}

Response&
Response::addRr(const std::string& rr)
{
  return this->addRr(makeBinaryBlock(ndns::tlv::RrData, rr.c_str(), rr.size()));
}

bool
Response::removeRr(const Block& rr)
{
  for (std::vector<Block>::iterator iter = m_rrs.begin(); iter != m_rrs.end(); ++iter) {
    if (*iter == rr) {
      m_rrs.erase(iter);
      return true;
    }
  }
  return false;
}

void
Response::setAppContent(const Block& block)
{
  if (block.type() != ndn::tlv::Content) {
    m_appContent = Block(ndn::tlv::Content, block);
  } else
    m_appContent = block;

  m_appContent.encode(); // this is a must
}


bool
Response::operator==(const Response& other) const
{
  bool tmp = (getZone() == other.getZone() &&
              getQueryType() == other.getQueryType() && getRrLabel() == other.getRrLabel() &&
              getRrType() == other.getRrType() && getVersion() == other.getVersion() &&
              getNdnsType() == other.getNdnsType());

  if (tmp == false)
    return tmp;

  if (m_ndnsType == NDNS_RAW) {
    return tmp && (getAppContent() == other.getAppContent());
  }
  else
    return tmp && getRrs() == other.getRrs();
}

std::ostream&
operator<<(std::ostream& os, const Response& response)
{
  os << "Response: zone=" << response.getZone()
     << " queryType=" << response.getQueryType()
     << " rrLabel=" << response.getRrLabel()
     << " rrType=" << response.getRrType()
     << " version=" << response.getVersion()
     << " freshnessPeriod=" << response.getFreshnessPeriod()
     << " ndnsType=" << response.getNdnsType();
  if (response.getNdnsType() == NDNS_RAW) {
    if (response.getAppContent().empty())
      os << " appContent=NULL";
    else
      os << " appContentSize=" << response.getAppContent().size();
  }
  else {
    os << " rrs.size=" << response.getRrs().size();
  }
  return os;
}
} // namespace ndns
} // namespace ndn
