/*
 * msgBuffer.cpp
 *
 *  Created on: Dec 2012
 *      Author: hariharanb
 */

#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <basicTypes.h>
#include <msgBuffer.h>

using namespace std;

using namespace cmn::utils;

MsgBuffer::MsgBuffer()
{
	initialize(DEFAULT_BUFF_SIZE);
}

MsgBuffer::MsgBuffer(uint16_t size)
{
	initialize(size);
}

MsgBuffer::~MsgBuffer()
{
	delete data_mp;
}

void MsgBuffer::initialize(uint16_t size)
{
	bufSize = size;
	data_mp = new uint8_t[size];
	memset(data_mp, 0, size);
	bitIndex = 0;
	byteIndex = 0;
	length = 0;
	bitLength = 0;
}

bool MsgBuffer::writeBits(uint8_t data, uint8_t size, bool append)
{

    uint8_t mask = (0xFF >> (8 - size));
    data = data & mask;

	if ((bitIndex + size) <= 8)
	{
		if (append)
		{
			goToEnd();
		}

		data_mp[byteIndex] = data_mp[byteIndex] | (data << (8-(bitIndex+size)));
		incrBitIndex(size);

		return true;

	}
	else
	{
		// Attempt to write beyond byte boundary
		return false;
	}
}

bool MsgBuffer::writeBytes(uint8_t* data, uint16_t size, bool append)
{
	bool rc = false;
	if (bitIndex == 0)
	{
		if (append)
		{
			goToEnd();
		}

		if ((byteIndex + size) <= bufSize)
		{
			memcpy(&data_mp[byteIndex], data, size);
			rc = incrByteIndex(size);
			if (byteIndex > length)
			{
				length = byteIndex;
			}
		}
	}
	return rc;
}

bool MsgBuffer::writeUint8(uint8_t data,  bool append)
{
	return writeBytes(&data, sizeof(uint8_t), append);
}

bool MsgBuffer::writeUint16(uint16_t data,  bool append)
{
	uint16_t localData = htons(data);
	return writeBytes((uint8_t*)&localData, sizeof(uint16_t), append);
}

bool MsgBuffer::writeUint32(uint32_t data,  bool append)
{
	uint32_t localData = htonl(data);
	return writeBytes((uint8_t*)&localData, sizeof(uint32_t), append);
}

bool MsgBuffer::writeUint64(uint64_t data, bool append)
{
	uint64_t localData = htonl(data);
	return writeBytes((uint8_t*)&localData, sizeof(uint64_t), append);
}

bool MsgBuffer::readBit()
{
	uint8_t byteValue = data_mp[byteIndex];
	uint8_t bitMask = 0x80;
	bitMask = bitMask >> bitIndex;

	// Adjust the indices
	incrBitIndex(1);

	if (byteValue & bitMask)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void MsgBuffer::readUint8(uint8_t &data)
{
	data = data_mp[byteIndex];
	nextByte();
}

bool MsgBuffer::readUint16(uint16_t &data)
{
	if ((byteIndex + sizeof(uint16_t)) <= length)
	{
		memcpy(&data, &data_mp[byteIndex], sizeof(uint16_t));
		data = ntohs(data);
		incrByteIndex(sizeof(uint16_t));
		return true;
	}
	else
	{
		return false;
	}
}

bool MsgBuffer::readUint32(uint32_t &data)
{
	if ((byteIndex + sizeof(uint32_t)) <= length)
	{
		memcpy(&data, &data_mp[byteIndex], sizeof(uint32_t));
		data = ntohl(data);
		incrByteIndex(sizeof(uint32_t));
		return true;
	}
	else
	{
		return false;
	}
}

bool MsgBuffer::readUint64(uint64_t &data)
{
	if ((byteIndex + sizeof(uint64_t)) <= length)
	{
		memcpy(&data, &data_mp[byteIndex], sizeof(uint64_t));
		data = ntohl(data);
		incrByteIndex(sizeof(uint64_t));
		return true;
	}
	else
	{
		return false;
	}
}

uint8_t MsgBuffer::readBits(uint16_t size)
{
	uint8_t data = 0;

	if ((bitIndex + size) > 8)
	{
		cout << "Attempt to read beyond byte boundary";
		return 0;
	}

	uint16_t i;
	for (i = 0; i <size; i++)
	{
		data = data << 1;
		if (readBit())
		{
			data = data | 0x0001;
		}
	}
	return data;
}


bool MsgBuffer::readBytes(uint8_t* data, uint16_t size)
{
	if ((byteIndex + size) <= length)
	{
		memcpy(data, &data_mp[byteIndex], size);
		byteIndex += size;
		bitIndex   = 0;
		return true;
	}
	else
	{
		return false;
	}


}

void MsgBuffer::rewind()
{
	bitIndex = 0;
	byteIndex = 0;
}

void MsgBuffer::reset()
{
	memset(data_mp, 0, length);
	rewind();
    length = 0;
    bitLength = 0;
}

void MsgBuffer::skipBits(uint8_t size)
{
	incrBitIndex(size);
}

void MsgBuffer::skipBytes(uint16_t size)
{
	incrByteIndex(size);
}

void MsgBuffer::display(Debug &stream)
{

}

bool MsgBuffer::incrBitIndex(uint8_t size)
{
    bool rc = false;
    if ((bitIndex + size) <= 8)
    {
    	uint16_t savedBitIndex = bitIndex;
    	bitIndex += size;
        rc = true;
    	if (bitIndex == 8)
    	{
    	  rc = incrByteIndex(1);
          bitIndex = 0;
    	}

    	if (!rc)
    	{
    		bitIndex = savedBitIndex;
    	}
    }
    // adjust the length now
    if ((byteIndex == length)&&(bitIndex > bitLength))
    {
      bitLength = bitIndex;
    }
    else if (byteIndex > length)
    {
      length = byteIndex;
      bitLength = bitIndex;
    }
    return rc;
}

bool MsgBuffer::incrByteIndex(uint16_t size)
{
	if ((byteIndex + size) <= bufSize)
	{
		byteIndex += size;
		return true;
	}
	else
	{
		return false;
	}
}

void MsgBuffer::nextByte()
{
	byteIndex++;
	if (byteIndex > length)
	{
		byteIndex = 0;
	}
	bitIndex = 0;
}

void MsgBuffer::goToEnd()
{
	byteIndex = length;
	bitIndex = bitLength;
}

uint16_t MsgBuffer::getLength()
{
       if (bitIndex == 0)
           return length;
       else
           return (length + 1);
}

uint16_t MsgBuffer::getBufferSize()
{
  return bufSize;
}

uint16_t MsgBuffer::getCurrentIndex()
{
       return byteIndex;
}

void MsgBuffer::goToIndex(uint16_t idx)
{
       byteIndex = idx;
}

uint16_t MsgBuffer::lengthLeft()
{
  return (length - byteIndex);
}

uint16_t MsgBuffer::sizeLeft()
{
  return (bufSize - byteIndex);
}

void* MsgBuffer::getDataPointer() 
{
  return data_mp;
}

void MsgBuffer::setLength(uint16_t bufLen)
{
  length = bufLen;
}

uint8_t MsgBuffer::charToHex (uint8_t x)
{
  if ((x >= '0') && (x <= '9'))
  {
    return (x - '0');
  }
  else if ((x >= 'a') && (x <= 'f'))
  {
    return (x - 'a' + 10);
  }
  else if ((x >= 'A') && (x <= 'F'))
  {
    return (x - 'A' + 10);
  }
  else
  {
    return 0;
  }
}

