/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014, 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"

namespace ndn {
namespace ndns {

Response::Response()
  : m_freshness(time::milliseconds(3600))
  , m_contentType(Query::QUERY_DNS)
  , m_responseType(NDNS_Resp)
{
}

Response::~Response()
{
}

template<bool T>
size_t Response::wireEncode(EncodingImpl<T> & block) const
{
  size_t totalLength = 0;
  std::vector<RR>::size_type lenOfRR = m_rrs.size();
  RR rr;
  Block btemp;

  //totalLength += m_rrs[0].wireEncode(block);

  for (std::vector<RR>::size_type i = 0; i < lenOfRR; i++) {
    rr = m_rrs[lenOfRR - i - 1];
    totalLength += rr.wireEncode(block);
    //std::cout<<"totalLenght="<<totalLength<<std::endl;
  }

  totalLength += prependNonNegativeIntegerBlock(block,
      ndn::ndns::tlv::ResponseNumberOfRRData, lenOfRR);

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

  totalLength += prependNonNegativeIntegerBlock(block,
      ndn::ndns::tlv::ResponseFressness, m_freshness.count());

  std::string msg = Response::toString(m_responseType);
  totalLength += prependByteArrayBlock(block, ndn::ndns::tlv::ResponseType,
      reinterpret_cast<const uint8_t*>(msg.c_str()), msg.size());

  totalLength += m_queryName.wireEncode(block);

  totalLength += block.prependVarNumber(totalLength);
  totalLength += block.prependVarNumber(Tlv::Content);
  return totalLength;
}

const Block&
Response::wireEncode() const
{

  if (m_wire.hasWire())
    return m_wire;
  EncodingEstimator estimator;

  size_t estimatedSize = wireEncode(estimator);
  //std::cout<< typeid( this).name()<<" Instance estimatedsize="<<estimatedSize<<std::endl;
  EncodingBuffer buffer(estimatedSize, 0);
  wireEncode(buffer);
  m_wire = buffer.block();
  return m_wire;
}

void Response::wireDecode(const Block& wire)
{
  if (!wire.hasWire()) {
    throw Tlv::Error("The supplied block does not contain wire format");
  }

  //if (wire.type() != ndn::ndns::tlv::ResponseContentBlob)
  //  throw Tlv::Error("Unexpected TLV type when decoding Content");

  m_wire = wire;
  m_wire.parse();

  Block::element_const_iterator it = m_wire.elements_begin();

  if (it != m_wire.elements_end() && it->type() == ndn::Tlv::Name) {
    m_queryName.wireDecode(*it);
    it++;
  } else {
    throw Tlv::Error("not the ndn::Tlv::Name type");
  }

  if (it != m_wire.elements_end()
      && it->type() == ndn::ndns::tlv::ResponseType) {
    std::string temp = std::string(reinterpret_cast<const char*>(it->value()),
        it->value_size());
    m_responseType = Response::toResponseType(temp);
    it++;
  } else {
    throw Tlv::Error("not the ndn::ndns::tlv::ReponseType type");
  }

  if (it != m_wire.elements_end()
      && it->type() == ndn::ndns::tlv::ResponseFressness) {
    m_freshness = time::milliseconds(readNonNegativeInteger(*it));
    it++;
  } else {
    throw Tlv::Error("not the ndn::ndns::tlv::ReponseFreshness type");
  }

  if (it != m_wire.elements_end()
      && it->type() == ndn::ndns::tlv::ResponseContentBlob) {
    //Block b2 = it->value();/* to check */
    Block b2 = *it;/* to check */

    b2.parse();
    Block::element_const_iterator it2 = b2.elements_begin();
    size_t rrlen = 0;
    if (it2 != b2.elements_end()
        && it2->type() == ndn::ndns::tlv::ResponseNumberOfRRData) {
      rrlen = readNonNegativeInteger(*it2);
      it2++;
    } else {
      throw Tlv::Error("not the ndn::ndns::tlv::ResponseNumberOfRRData type");
    }
    for (size_t i = 0; i < rrlen; i++) {
      if (it2 != b2.elements_end() && it2->type() == ndn::ndns::tlv::RRData) {
        RR rr;
        rr.wireDecode(*it2);
        this->m_rrs.push_back(rr);
        it2++;
      } else {
        throw Tlv::Error("not the ndn::ndns::tlv::RRData type");
      }
    }

    it++;
  } else {
    throw Tlv::Error("not the ndn::ndns::tlv::ResponseContentBlob type");
  }

}

void Response::fromData(const Data& data)
{

  m_queryName = data.getName();
  m_freshness = data.getFreshnessPeriod();
  m_contentType = Query::QueryType(data.getContentType());
  this->wireDecode(data.getContent());
}

void Response::fromData(const Name& name, const Data& data)
{
  fromData(data);
}

Data Response::toData() const
{
  Data data;
  data.setName(m_queryName);
  data.setFreshnessPeriod(this->m_freshness);
  data.setContentType(m_contentType);
  data.setContent(this->wireEncode());

  return data;
}

} // namespace ndns
} // namespace ndn
