// HistoryBuffer.cpp: implementation of the CHistoryBuffer class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "HistoryBuffer.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CHistoryBuffer::CHistoryBuffer()
{
	m_byDataBuffer		= NULL;
	m_uiFront			= 0;
	m_uiRear			= 0;
	m_uiTotalRecords	= 0;															
	m_uiMaxRecords		= 0;									
	m_uiMaxLineBytes	= 0;		
}

CHistoryBuffer::~CHistoryBuffer()
{
	if(m_byDataBuffer)
		delete [] m_byDataBuffer;

	m_byDataBuffer = NULL;
}

BOOL CHistoryBuffer::Configure(ULONG cx, ULONG cy)
{
	//Check for valid size
	if((cx*cy)==0)
		return FALSE;

	m_uiMaxRecords   = cy;
	m_uiMaxLineBytes = cx;


	//Check if allocated
	if(m_byDataBuffer)
		delete [] m_byDataBuffer;
	m_byDataBuffer = NULL;

	//Reallocate
	m_byDataBuffer = new BYTE[cx*cy];
	
	//Check again
	if(m_byDataBuffer == NULL)
		return FALSE;

	//Initialize the vector
	RECORD rec;
	rec.lBytes = 0;
	rec.data = NULL;
	for(int i = 0; i < cy; i++)
	{	
		m_vecHistoryBuffer.push_back(rec);
		m_vecHistoryBuffer[i].data = (m_byDataBuffer + (i*cx));
	}

	//Init fron/rear
	m_uiFront = m_uiRear = 0;

	return TRUE;
}

RECORD *CHistoryBuffer::AddData(BYTE *byInput, UINT uiSize)
{
	//TRACE("ADDING TO FRONT = %d\r\n", m_uiFront);
	//get Pointer to front of buffer
	RECORD *front = &(m_vecHistoryBuffer[m_uiFront]);

	//Zero out any existing values if there
	if(front->lBytes)
		ZeroMemory((void*)front->data, front->lBytes); 
	
	//Copy in our new data, and check
	if(memcpy((void*)front->data, byInput, uiSize) == NULL)
	{
		return NULL;
	}

	front->lBytes = uiSize;

	//increment total records only if are size is
	//less than the max records
	if(m_uiTotalRecords < m_uiMaxRecords)
		m_uiTotalRecords++;
	
	//Check if out of range...
	//else increment the front index to next record	
	
	m_uiFront++;
	
	if(m_uiFront == m_uiMaxRecords)
		m_uiFront = 0;
	
	//TRACE("NEXT FRONT = %d\r\n\r\n", m_uiFront);

	//return a pointer to record we just added
	if(m_uiFront == 0)
	{
		return &m_vecHistoryBuffer[m_uiMaxRecords-1];
	}
	
	return &m_vecHistoryBuffer[m_uiFront-1];
}

RECORD *CHistoryBuffer::GetRecord(UINT uiIndex)
{
	if(uiIndex > m_uiTotalRecords-1)
		return NULL;

	//TRACE("GETTING RECORD INDEX: %d\r\n", uiIndex);

	//We internally manage the index, because this is a ring buffer.
	//The index arg must be scaled to an actual index in terms of
	//our marker for the current front of the buffer. note, that front
	//points to the next cell to fill, so an index request of [0]
	//means we want the cell[front-1]
	//

	//Our actual cell is the front minus the index
	//so check if that is within range
	
	int test = (m_uiFront-1)-uiIndex;

	if(test >= 0)
	{	
		//TRACE("GOT RECORD, BUFF INDEX = %d\r\n\r\n", test);
		return &m_vecHistoryBuffer[test];
	}
	else if(test == -1)
	{	
		int offset = m_uiMaxRecords-1;
		//TRACE("*GOT RECORD, BUFF INDEX = %d\r\n\r\n",m_uiTotalRecords-offset);
		return &m_vecHistoryBuffer[offset];
	}
	else
	{
		//TRACE("UNACCOUNTED CONDITION MET\r\n");
		
		//ASSERT(0);
	}
	//If we get here there is a serious problem... 
	return NULL;
}

RECORD *CHistoryBuffer::GetNextRecord( void )
{
	if(m_uiTotalRecords == 0)
		return NULL;
	//TRACE("GET NEXT RECORD ()\r\n");
	//TRACE("Getting Record #%d out of %d\r\n\r\n", m_uiTotalRecords-1, m_uiTotalRecords);

	RECORD *temp = GetRecord(m_uiTotalRecords-1);

	m_uiTotalRecords -= 1;
	if(m_uiTotalRecords < 0)
		m_uiTotalRecords = 0;

	return temp;
}

UINT CHistoryBuffer::GetCount()
{
	return m_uiTotalRecords;
}