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

#include <boost/endian/conversion.hpp>

namespace ndn {
namespace encoding {

namespace endian = boost::endian;

Encoder::Encoder(size_t totalReserve, size_t reserveFromBack)
  : m_buffer(make_shared<Buffer>(totalReserve))
{
  m_begin = m_end = m_buffer->end() - (reserveFromBack < totalReserve ? reserveFromBack : 0);
}

Encoder::Encoder(const Block& block)
  : m_buffer(const_pointer_cast<Buffer>(block.getBuffer()))
  , m_begin(m_buffer->begin() + (block.begin() - m_buffer->begin()))
  , m_end(m_buffer->begin()   + (block.end()   - m_buffer->begin()))
{
}

void
Encoder::reserveBack(size_t size)
{
  if (m_end + size > m_buffer->end())
    reserve(m_buffer->size() * 2 + size, false);
}

void
Encoder::reserveFront(size_t size)
{
  if (m_buffer->begin() + size > m_begin)
    reserve(m_buffer->size() * 2 + size, true);
}

Block
Encoder::block(bool verifyLength) const
{
  return Block(m_buffer, m_begin, m_end, verifyLength);
}

void
Encoder::reserve(size_t size, bool addInFront)
{
  if (size < m_buffer->size()) {
    size = m_buffer->size();
  }

  if (addInFront) {
    size_t diffEnd = m_buffer->end() - m_end;
    size_t diffBegin = m_buffer->end() - m_begin;

    Buffer* buf = new Buffer(size);
    std::copy_backward(m_buffer->begin(), m_buffer->end(), buf->end());

    m_buffer.reset(buf);

    m_end = m_buffer->end() - diffEnd;
    m_begin = m_buffer->end() - diffBegin;
  }
  else {
    size_t diffEnd = m_end - m_buffer->begin();
    size_t diffBegin = m_begin - m_buffer->begin();

    Buffer* buf = new Buffer(size);
    std::copy(m_buffer->begin(), m_buffer->end(), buf->begin());

    m_buffer.reset(buf);

    m_end = m_buffer->begin() + diffEnd;
    m_begin = m_buffer->begin() + diffBegin;
  }
}

size_t
Encoder::prependByte(uint8_t value)
{
  reserveFront(1);

  m_begin--;
  *m_begin = value;
  return 1;
}

size_t
Encoder::appendByte(uint8_t value)
{
  reserveBack(1);

  *m_end = value;
  m_end++;
  return 1;
}

size_t
Encoder::prependByteArray(const uint8_t* array, size_t length)
{
  reserveFront(length);

  m_begin -= length;
  std::copy(array, array + length, m_begin);
  return length;
}

size_t
Encoder::appendByteArray(const uint8_t* array, size_t length)
{
  reserveBack(length);

  std::copy(array, array + length, m_end);
  m_end += length;
  return length;
}

size_t
Encoder::prependVarNumber(uint64_t varNumber)
{
  if (varNumber < 253) {
    prependByte(static_cast<uint8_t>(varNumber));
    return 1;
  }
  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
    uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
    prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
    prependByte(253);
    return 3;
  }
  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
    uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
    prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
    prependByte(254);
    return 5;
  }
  else {
    uint64_t value = endian::native_to_big(varNumber);
    prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
    prependByte(255);
    return 9;
  }
}

size_t
Encoder::appendVarNumber(uint64_t varNumber)
{
  if (varNumber < 253) {
    appendByte(static_cast<uint8_t>(varNumber));
    return 1;
  }
  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
    appendByte(253);
    uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
    appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
    return 3;
  }
  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
    appendByte(254);
    uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
    appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
    return 5;
  }
  else {
    appendByte(255);
    uint64_t value = endian::native_to_big(varNumber);
    appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
    return 9;
  }
}

size_t
Encoder::prependNonNegativeInteger(uint64_t varNumber)
{
  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
    return prependByte(static_cast<uint8_t>(varNumber));
  }
  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
    uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
    return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
  }
  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
    uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
    return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
  }
  else {
    uint64_t value = endian::native_to_big(varNumber);
    return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
  }
}

size_t
Encoder::appendNonNegativeInteger(uint64_t varNumber)
{
  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
    return appendByte(static_cast<uint8_t>(varNumber));
  }
  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
    uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
    return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
  }
  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
    uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
    return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
  }
  else {
    uint64_t value = endian::native_to_big(varNumber);
    return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
  }
}

size_t
Encoder::prependByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
{
  size_t totalLength = prependByteArray(array, arraySize);
  totalLength += prependVarNumber(arraySize);
  totalLength += prependVarNumber(type);

  return totalLength;
}

size_t
Encoder::appendByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
{
  size_t totalLength = appendVarNumber(type);
  totalLength += appendVarNumber(arraySize);
  totalLength += appendByteArray(array, arraySize);

  return totalLength;
}

size_t
Encoder::prependBlock(const Block& block)
{
  if (block.hasWire()) {
    return prependByteArray(block.wire(), block.size());
  }
  else {
    return prependByteArrayBlock(block.type(), block.value(), block.value_size());
  }
}

size_t
Encoder::appendBlock(const Block& block)
{
  if (block.hasWire()) {
    return appendByteArray(block.wire(), block.size());
  }
  else {
    return appendByteArrayBlock(block.type(), block.value(), block.value_size());
  }
}

} // namespace encoding
} // namespace ndn
