/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NSCRIPTPROFILER__
#define	__NSCRIPTPROFILER__


		#include "nstring/nstring.h"
		#include "container/nlist.h"


namespace GS {
	namespace Script {

/*
	@short	Script VM profiler.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class		Profiler
{
public:

struct		FunctionProfile
{
	String			func,				///< The function name.
					source;				///< The source name.
	int				line;				///< Function start line.

	int				hit_count,			///< Number of total call to this function.
					total_clock,		///< Total execution clock.
					self_clock;

	List <FunctionProfile *> callee_function;
	FunctionProfile	*caller_function;

	/// Hit function profile.
	void		Hit() { hit_count++; }
	/// Update function profile.
	void		Update(int dt_clock, int /*line*/) { self_clock += dt_clock; }

	FunctionProfile(const char *sourcename, const char *funcname, int _line)
	{
		source = sourcename;
		func = funcname;
		line = _line;

		caller_function = 0;
		hit_count = 0;
		total_clock = 0;
		self_clock = 0;
	}
};

protected:

		int				profiler_clock,
						total_clock;
		bool			profiling;

		FunctionProfile	*current_function_profile;

public:

		String			id;								///< Profiler session id.

		/// Profiled function stack.
		List <FunctionProfile *> function_map;			///< The profiled function map (all profiles from the call graph).
		List <FunctionProfile *> function_list;			///< The profiled function list (each function figures only once in this list).

		/// Get child total clock.
		int				GetChildTotalClock(FunctionProfile *profile);
		/// Get the last profile session total running clock.
		int				GetTotalClock() const { return total_clock; }

		/// Is a profiler session opened.
		bool			IsProfiling() const { return profiling; }

		/// Request a function profile.
		FunctionProfile	*GetFunctionProfile(const char *source, const char *func, int line, FunctionProfile *caller);
		/// Invalidate the current function profile.
		void			InvalidateCurrentFunctionProfile() { current_function_profile = 0; }

		/// Start a profiler session.
		void			Start(const char *session_id);
		/// Update profiler.
		void			Update(int type, FunctionProfile *profile);
		/// End a profiler session.
		void			End();

		Profiler();
};

	} // Script
} // GS


#endif	// __NSCRIPTPROFILER__
