//////////////////////////////////////////////////////////////////////////////
//
// Asura_Profiling_System.h
//
// Copyright (c) 2004 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___ASURA_PROFILING_H___
#define ___ASURA_PROFILING_H___ 1

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

#include "Core/Asura_Handle.h"
#include "Core/Asura_Platform_Timers.h"

#ifdef ASURA_USE_PROFILING_SYSTEM

//////////////////////////////////////////////////////////////////////////////
//
// Asura_Profiling_System
//
// Grab a timer using CreateTimer and then use its handle in the timing functions.
// When you're done with it use DestroyTimer to free it up for something else.
// All durations are in seconds.
//
// NOTE: If you use the wrappers below to access the profiling system, rather
// than calling the methods directly then you can easily take the code out of
// builds by commenting out the #define ASURA_USE_PROFILING_SYSTEM in your
// engine configuration file.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef ASURA_PROFILING_SYSTEM_MAX_TIMERS
	#define ASURA_PROFILING_SYSTEM_MAX_TIMERS (64)
#endif

class Asura_Profiling_System
{
public:
    static void Initialise();

    // timer functions
    static Asura_Handle CreateTimer();
    static void         DestroyTimer( const Asura_Handle iTimerHandle );
    static void         ResetTimer( const Asura_Handle iTimerHandle );

    // timing functions
    static void				StartTiming        ( const Asura_Handle iTimerHandle );
    static Asura_TickCount	StopTiming         ( const Asura_Handle iTimerHandle ); // returns the duration
    static float        	GetMinDuration     ( const Asura_Handle iTimerHandle );
    static float        	GetMaxDuration     ( const Asura_Handle iTimerHandle );
    static float        	GetAverageDuration ( const Asura_Handle iTimerHandle );
    static unsigned int 	GetTriggerCount    ( const Asura_Handle iTimerHandle );
    static float        	GetTotalDuration   ( const Asura_Handle iTimerHandle );

private:
    struct Timer
    {
        Asura_TickCount	m_xTotalDuration;
        Asura_TickCount	m_xMinDuration;
        Asura_TickCount	m_xMaxDuration;
        unsigned int	m_uTriggerCount;
        unsigned char	m_ucInUse  : 1;
        unsigned char	m_ucTiming : 1;

        void Reset();
    };
    static Timer s_axTimers[ ASURA_PROFILING_SYSTEM_MAX_TIMERS ];
};

//////////////////////////////////////////////////////////////////////////////
//
// wrappers
//
//////////////////////////////////////////////////////////////////////////////

#define Asura_Profiling_CreateTimer                   Asura_Profiling_System::CreateTimer
#define Asura_Profiling_DestroyTimer( iHandle )       Asura_Profiling_System::DestroyTimer( iHandle )
#define Asura_Profiling_ResetTimer(iHandle)			  Asura_Profiling_System::ResetTimer(iHandle)
#define Asura_Profiling_StartTiming( iHandle )        Asura_Profiling_System::StartTiming( iHandle )
#define Asura_Profiling_StopTiming( iHandle )         Asura_Profiling_System::StopTiming( iHandle )
#define Asura_Profiling_GetMinDuration( iHandle )     Asura_Profiling_System::GetMinDuration( iHandle )
#define Asura_Profiling_GetMaxDuration( iHandle )     Asura_Profiling_System::GetMaxDuration( iHandle )
#define Asura_Profiling_GetAverageDuration( iHandle ) Asura_Profiling_System::GetAverageDuration( iHandle )
#define Asura_Profiling_GetTriggerCount( iHandle )    Asura_Profiling_System::GetTriggerCount( iHandle )
#define Asura_Profiling_GetTotalDuration( iHandle )   Asura_Profiling_System::GetTotalDuration( iHandle )

//////////////////////////////////////////////////////////////////////////////
//
// 
//
//////////////////////////////////////////////////////////////////////////////

#else // #ifdef ASURA_USE_PROFILING_SYSTEM

#include "Core/Asura_Handle.h"

// The pointless handle assignments below are to stop compiler complaining
// about "statement with no effect".

#define Asura_Profiling_CreateTimer()                 ASURA_INVALID_HANDLE
#define Asura_Profiling_DestroyTimer( iHandle )       (iHandle=iHandle,(void)0)
#define Asura_Profiling_ResetTimer(iHandle)           (iHandle=iHandle,(void)0)
#define Asura_Profiling_StartTiming( iHandle )        (iHandle=iHandle,(void)0)
#define Asura_Profiling_StopTiming( iHandle )         (iHandle=iHandle,static_cast<Asura_TickCount>(0.0f))
#define Asura_Profiling_GetMinDuration( iHandle )     (iHandle=iHandle,0.0f)
#define Asura_Profiling_GetMaxDuration( iHandle )     (iHandle=iHandle,0.0f)
#define Asura_Profiling_GetAverageDuration( iHandle ) (iHandle=iHandle,0.0f)
#define Asura_Profiling_GetTriggerCount( iHandle )    (iHandle=iHandle,0)
#define Asura_Profiling_GetTotalDuration( iHandle )   (iHandle=iHandle,0.0f)

#endif // #ifdef ASURA_USE_PROFILING_SYSTEM

#endif // #ifndef ___ASURA_PROFILING_H___
