/**
 * @author: Jeff Thompson
 * Derived from BinaryXMLEncoder.js by Meki Cheraoui.
 * See COPYING for copyright and distribution information.
 */

#include <math.h>
#include "../util/ndn_memory.h"
#include "binary-xml.h"
#include "binary-xml-encoder.h"

enum {
  ENCODING_LIMIT_1_BYTE = ((1 << ndn_BinaryXml_TT_VALUE_BITS) - 1),
  ENCODING_LIMIT_2_BYTES = ((1 << (ndn_BinaryXml_TT_VALUE_BITS + ndn_BinaryXml_REGULAR_VALUE_BITS)) - 1),
  ENCODING_LIMIT_3_BYTES = ((1 << (ndn_BinaryXml_TT_VALUE_BITS + 2 * ndn_BinaryXml_REGULAR_VALUE_BITS)) - 1)
};

/**
 * Call ndn_DynamicUCharArray_ensureLength to ensure that there is enough room in the output, and copy
 * array to the output.  This does not write a header.
 * @param self pointer to the ndn_BinaryXmlEncoder struct
 * @param array the array to copy
 * @param arrayLength the length of the array
 * @return 0 for success, else an error code
 */
static ndn_Error writeArray(struct ndn_BinaryXmlEncoder *self, unsigned char *array, unsigned int arrayLength)
{
  ndn_Error error;
  if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + arrayLength)))
    return error;
  
  ndn_memcpy(self->output->array + self->offset, array, arrayLength);
  self->offset += arrayLength;
  
  return NDN_ERROR_success;
}

/**
 * Return the number of bytes to encode a header of value x.
 */
static unsigned int getNHeaderEncodingBytes(unsigned int x) 
{
  // Do a quick check for pre-compiled results.
  if (x <= ENCODING_LIMIT_1_BYTE) 
    return 1;
  if (x <= ENCODING_LIMIT_2_BYTES) 
    return 2;
  if (x <= ENCODING_LIMIT_3_BYTES) 
    return 3;
  
  unsigned int nBytes = 1;
  
  // Last byte gives you TT_VALUE_BITS.
  // Remainder each gives you REGULAR_VALUE_BITS.
  x >>= ndn_BinaryXml_TT_VALUE_BITS;
  while (x != 0) {
    ++nBytes;
    x >>= ndn_BinaryXml_REGULAR_VALUE_BITS;
  }
  
  return nBytes;
}

/**
 * Reverse the length bytes in array.
 * @param array
 * @param length
 */
static void reverse(unsigned char *array, unsigned int length) 
{
  if (length == 0)
    return;
  
  unsigned char *left = array;
  unsigned char *right = array + length - 1;
  while (left < right) {
    // Swap.
    unsigned char temp = *left;
    *left = *right;
    *right = temp;
    
    ++left;
    --right;
  }
}

/**
 * Write x as an unsigned decimal integer to the output with the digits in reverse order, using ndn_DynamicUCharArray_ensureLength.
 * This does not write a header.
 * We encode in reverse order, because this is the natural way to encode the digits, and the caller can reverse as needed.
 * @param self pointer to the ndn_BinaryXmlEncoder struct
 * @param x the unsigned int to write
 * @return 0 for success, else an error code
 */
static ndn_Error encodeReversedUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int x) 
{
  while (1) {
    ndn_Error error;
    if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + 1)))
      return error;
    
    self->output->array[self->offset++] = (unsigned char)(x % 10 + '0');
    x /= 10;
    
    if (x == 0)
      break;
  }
  
  return NDN_ERROR_success;
}

/**
 * Reverse the buffer in self->output->array, then shift it right by the amount needed to prefix a header with type, 
 * then encode the header at startOffset.
 * startOffser it the position in self-output.array of the first byte of the buffer and self->offset is the first byte past the end.
 * We reverse and shift in the same function to avoid unnecessary copying if we first reverse then shift.
 * @param self pointer to the ndn_BinaryXmlEncoder struct
 * @param startOffset the offset in self->output->array of the start of the buffer to shift right
 * @param type the header type
 * @return 0 for success, else an error code
 */
static ndn_Error reverseBufferAndInsertHeader
  (struct ndn_BinaryXmlEncoder *self, unsigned int startOffset, unsigned int type)
{
  unsigned int nBufferBytes = self->offset - startOffset;
  unsigned int nHeaderBytes = getNHeaderEncodingBytes(nBufferBytes);
  ndn_Error error;
  if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + nHeaderBytes)))
    return error;
  
  // To reverse and shift at the same time, we first shift nHeaderBytes to the destination while reversing,
  //   then reverse the remaining bytes in place.
  unsigned char *from = self->output->array + startOffset;
  unsigned char *fromEnd = from + nHeaderBytes;
  unsigned char *to = self->output->array + startOffset + nBufferBytes + nHeaderBytes - 1;
  while (from < fromEnd)
    *(to--) = *(from++);
  // Reverse the remaining bytes in place (if any).
  if (nBufferBytes > nHeaderBytes)
    reverse(self->output->array + startOffset + nHeaderBytes, nBufferBytes - nHeaderBytes);
  
  // Override the offset to force encodeTypeAndValue to encode at startOffset, then fix the offset.
  self->offset = startOffset;
  if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, type, nBufferBytes)))
    // We don't really expect to get an error, since we have already ensured the length.
    return error;
  self->offset = startOffset + nHeaderBytes + nBufferBytes;
  
  return NDN_ERROR_success;
}

/**
 * Split the absolute value of x, rounded to an integer into 32 bit unsigned integers hi32 and lo32.
 * We need this because not all C compilers support 64 bit long long integers, so we carry around
 * a high precision value as a double, which we assume has more than 32 bits.
 * But we want to do bit-wise operations on integers.
 * @param x the double value
 * @param hi32 output the high 32 bits
 * @param lo32 output the low 32 bits
 */
static inline void splitAbsDouble(double x, unsigned long *hi32, unsigned long *lo32)
{
  if (x < 0)
    x = -x;
  x = round(x);
  
  double twoPower32 = 4294967296.0;
  double lo32Double = fmod(x, twoPower32);
  *lo32 = (unsigned long)lo32Double;
  *hi32 = (unsigned long)((x - lo32Double) / twoPower32);
}

ndn_Error ndn_BinaryXmlEncoder_encodeTypeAndValue(struct ndn_BinaryXmlEncoder *self, unsigned int type, unsigned int value)
{
  if (type > ndn_BinaryXml_UDATA)
    return NDN_ERROR_header_type_is_out_of_range;
  
  // Encode backwards. Calculate how many bytes we need.
  unsigned int nEncodingBytes = getNHeaderEncodingBytes(value);
  ndn_Error error;
  if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + nEncodingBytes)))
    return error;

  // Bottom 4 bits of value go in last byte with tag.
  self->output->array[self->offset + nEncodingBytes - 1] = 
    (ndn_BinaryXml_TT_MASK & type | 
    ((ndn_BinaryXml_TT_VALUE_MASK & value) << ndn_BinaryXml_TT_BITS)) |
    ndn_BinaryXml_TT_FINAL; // set top bit for last byte
  value >>= ndn_BinaryXml_TT_VALUE_BITS;
  
  // Rest of value goes into preceding bytes, 7 bits per byte. (Zero top bit is "more" flag.)
  unsigned int i = self->offset + nEncodingBytes - 2;
  while (value != 0 && i >= self->offset) {
    self->output->array[i] = (value & ndn_BinaryXml_REGULAR_VALUE_MASK);
    value >>= ndn_BinaryXml_REGULAR_VALUE_BITS;
    --i;
  }
  if (value != 0)
    // This should not happen if getNHeaderEncodingBytes is correct.
    return NDN_ERROR_encodeTypeAndValue_miscalculated_N_encoding_bytes;
  
  self->offset+= nEncodingBytes;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeElementClose(struct ndn_BinaryXmlEncoder *self)
{
  ndn_Error error;
  if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + 1)))
    return error;
  
  self->output->array[self->offset] = ndn_BinaryXml_CLOSE;
  self->offset += 1;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeBlob(struct ndn_BinaryXmlEncoder *self, unsigned char *value, unsigned int valueLength)
{
  ndn_Error error;
  if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_BLOB, valueLength)))
    return error;
  
  if ((error = writeArray(self, value, valueLength)))
    return error;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeBlobDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, unsigned char *value, unsigned int valueLength)
{
  ndn_Error error;
  if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
    return error;
  
  if ((error = ndn_BinaryXmlEncoder_writeBlob(self, value, valueLength)))
    return error;  
  
  if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
    return error;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeUData(struct ndn_BinaryXmlEncoder *self, unsigned char *value, unsigned int valueLength)
{
  ndn_Error error;
  if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_UDATA, valueLength)))
    return error;
  
  if ((error = writeArray(self, value, valueLength)))
    return error;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeUDataDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, unsigned char *value, unsigned int valueLength)
{
  ndn_Error error;
  if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
    return error;
  
  if ((error = ndn_BinaryXmlEncoder_writeUData(self, value, valueLength)))
    return error;  
  
  if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
    return error;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int value)
{
  // First write the decimal int (to find out how many bytes it is), then shift it forward to make room for the header.
  unsigned int startOffset = self->offset;
  
  ndn_Error error;
  if ((error = encodeReversedUnsignedDecimalInt(self, value)))
    return error;
  
  if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_UDATA)))
    return error;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalIntDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, unsigned int value)
{
  ndn_Error error;
  if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
    return error;
  
  if ((error = ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(self, value)))
    return error;  
  
  if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
    return error;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXmlEncoder *self, double value)
{
  unsigned long hi32, lo32;
  splitAbsDouble(value, &hi32, &lo32);
  
  // First encode the big endian backwards, then reverseBufferAndInsertHeader will reverse it.
  unsigned int startOffset = self->offset;
  
  ndn_Error error;
  while (lo32 != 0) {
    if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + 1)))
      return error;
    
    self->output->array[self->offset++] = (unsigned char)(lo32 & 0xff);
    lo32 >>= 8;
  }
  
  if (hi32 != 0) {
    // Pad the lo values out to 4 bytes.
    while (self->offset - startOffset < 4) {
      if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + 1)))
        return error;
    
      self->output->array[self->offset++] = 0;
    }
    
    // Encode hi32
    while (hi32 != 0) {
      if ((error = ndn_DynamicUCharArray_ensureLength(self->output, self->offset + 1)))
        return error;
    
      self->output->array[self->offset++] = (unsigned char)(hi32 & 0xff);
      hi32 >>= 8;
    }
  }
  
  if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_BLOB)))
    return error;
  
  return NDN_ERROR_success;
}

ndn_Error ndn_BinaryXmlEncoder_writeTimeMillisecondsDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, double milliseconds)
{
  ndn_Error error;
  if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
    return error;
   
  if ((error = ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(self, (milliseconds / 1000.0) * 4096.0)))
    return error;
    
  if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
    return error;
  
  return NDN_ERROR_success;
}
