#include "clock.h"

CClock::CClock(void)
{
	m_FPSInterval = 333;
	LARGE_INTEGER qwTicksPerSec;
    m_bUsingQPF = (QueryPerformanceFrequency( &qwTicksPerSec ) != 0);
    if( m_bUsingQPF )
		m_TicksPerSec = qwTicksPerSec.QuadPart;
    
	Reset();
}

CClock::~CClock(void)
{
	m_CaptureTimes.Clear();
}

void CClock::Reset(void)
{
	QueryPerformanceCounter( &m_StartTime );
	m_LastFrame=m_StartTime;
	m_FrameTime=0;
	m_ThisFrame=m_StartTime;
	m_RunTime.QuadPart=0;
	m_dwRunTime=0;
	m_AvgFPS=0.f;
	m_AvgFPSAllFrames=0.f;
	m_AnimMultiplier=0.f;
	m_FrameCounter=0;
	m_LastFPSUpdate.QuadPart=0;
	m_FPSFrameCounter = 0;
}

void CClock::Tick(void)
{
	m_FrameCounter++;
	m_FPSFrameCounter++;
	m_LastFrame=m_ThisFrame;
	QueryPerformanceCounter( &m_ThisFrame );
	m_FrameTime=(DWORD)(m_ThisFrame.QuadPart-m_LastFrame.QuadPart);
	m_AnimMultiplier=(float)m_FrameTime/(float)m_TicksPerSec;
	m_RunTime.QuadPart=m_ThisFrame.QuadPart-m_StartTime.QuadPart;
	m_dwRunTime = (DWORD)(m_RunTime.QuadPart*1000/m_TicksPerSec);
	m_AvgFPSAllFrames=(float)m_FrameCounter*(float)m_TicksPerSec/(float)m_RunTime.QuadPart;

	unsigned dtlastfpsupdate = (m_RunTime.QuadPart-m_LastFPSUpdate.QuadPart) * 1000 / m_TicksPerSec;
	if (dtlastfpsupdate >= m_FPSInterval)
	{
		m_AvgFPS = (float)m_FPSFrameCounter*1000.f/dtlastfpsupdate;
		m_LastFPSUpdate.QuadPart = m_RunTime.QuadPart;
		m_FPSFrameCounter=0;
	}
}

void CClock::StartCapture(const unsigned CaptureID)
{
	ListElement<LONGLONG> *ct = NULL;

	ct = m_CaptureTimes.GetElement(CaptureID);
	if(!ct)
	{
		ct = new ListElement<LONGLONG>(new LONGLONG,CaptureID);
		m_CaptureTimes.AddHead(ct);
	}

	LARGE_INTEGER Time;
	QueryPerformanceCounter( &Time );
	*ct->GetInfo() = Time.QuadPart;
}

void CClock::EndCapture(const unsigned CaptureID)
{
	ListElement<LONGLONG> *ct = NULL;

	ct = m_CaptureTimes.GetElement(CaptureID);
	if(!ct)
		return;
		
	LARGE_INTEGER Time;
	QueryPerformanceCounter( &Time );

	*ct->GetInfo() = Time.QuadPart - *ct->GetInfo();
}

LONGLONG CClock::GetCaptureTime(const unsigned CaptureID) const
{
	ListElement<LONGLONG> *ct = NULL;

	ct = m_CaptureTimes.GetElement(CaptureID);
	if(!ct)
		return 0;

	return *ct->GetInfo();
}

void CClock::ClearCapture(const unsigned CaptureID)
{
	ListElement<LONGLONG> *ct = NULL;

	ct = m_CaptureTimes.GetElement(CaptureID);
	if(ct)
		ct->Delete();
}