/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/include/sgx/core/time/gameclock.hpp

*/

#ifndef SGX_CORE_TIME_GAMECLOCK_HPP
#define SGX_CORE_TIME_GAMECLOCK_HPP	1

#include "sgx/core/types/types.hpp"

#define MAX_TIMERS		16

class CClockTimer;
class sgxGameClockCallbackHandler {
public:
	virtual tBOOL	onGameClockTimer(CClockTimer *pTimer);
};


class CClockTimer {
public:
	tUINT32		m_iRepeatCount;
	tUINT32		m_iRepeatStop;
	tUINT32		m_iUserData;
	tREAL32		m_fPeriod;
	tREAL32		m_fFrequencyFPS;

	CClockTimer();

	void							start(const tREAL32 period, sgxGameClockCallbackHandler *pHandler=NULL, const tUINT32 maxRepeats=0);
	void							startFPS(const tREAL32 fps, sgxGameClockCallbackHandler *pHandler=NULL, const tUINT32 maxRepeats=0);
	void							stop();
	void							pause();
	void							resume();
	tBOOL							isRunning() const;
	tBOOL							isValid() const;
	void							update(const tREAL32 telaps);
	void							setHandler(sgxGameClockCallbackHandler *pHandler);
	sgxGameClockCallbackHandler *	getHandler() const;

protected:

	tBOOL							m_bRunning;
	tBOOL							m_bPaused;
	tREAL32							m_fTimecumNext;
	sgxGameClockCallbackHandler *	m_pHandler;
};
	
class CGameClock {
public:
    CGameClock();

    tREAL32		applyRealTimeToClock(tREAL32 current_time);
    void		setModeRealtime();
    void		setModeConstant(const tREAL32 period);
    void		setModeConstantFPS(const tREAL32 fps);
    void		setModeClamped(const tREAL32 min_fps, const tREAL32 max_fps=60);
	void		setModeClampedTelaps(const tREAL32 min_telaps, const tREAL32 max_telaps);
    tREAL32		getTime();
	tREAL32		getLastTelaps();
	tREAL32		getClampedMin();
	tREAL32		getClampedMax();
    tREAL32		update(const tREAL32 telaps);
	//
	CClockTimer *	getFreeTimer();
	void			releaseAllTimers(const sgxGameClockCallbackHandler *pWithHandler=NULL);


    typedef enum {
        Realtime,
        AsGiven,
        Constant,
        Clamped
    } CClockMode;

    static	CGameClock * get();

protected:
    static CGameClock      *sm_pSingleton;

private:
    tREAL32                 m_fLastTime;
    tREAL32                 m_fFractionalSpeed;
    tREAL32                 m_fGivenTime;
    tREAL32                 m_fConstantPeriod;
    tREAL32                 m_fClampedMin;
    tREAL32                 m_fClampedMax;
	tREAL32					m_fLastTelaps;
    CClockMode              m_ClockMode;

	tUINT32					m_MaxTimers;
	CClockTimer				m_Timer[MAX_TIMERS];

};

#endif /* SGX_CORE_TIME_GAMECLOCK_HPP */
