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


		#include "scene3d/scene.h"
		#include "physic/physic_world.h"
		#include "core/renderer.h"

		using namespace GS;
		using namespace GS::S3D;


namespace GS {

//
class	ProfilerRenderer
{
		Renderer	&render;
		RasterFont	**font;

		float		&x, &y;

		Renderer::WriterConfig config;

		Color		title_color;

static	const int	indent_width = 16;
static	const int	col_a_x = 180, col_b_x = 256;

		void		DisplaySystem(const char *label, const Benchmark &bench)
		{
			float x_h = x;
			render.Write(*font[0], label, x_h, y, config, 1, &title_color);

			float x_a = x + col_a_x;
			render.Write(*font[0], String::Format("%0.02fms", bench.GetMs()), x_a, y, config, 1, &title_color);
			float x_b = x + col_b_x;
			render.Write(*font[0], bench.GetMs() ? String::Format("%.01ffps", 1000.f / bench.GetMs()) : "-", x_b, y, config, 1, &title_color);

			render.Write(*font[0], "\n", x, y, config, 1, &title_color);
		}
		void		DisplaySystem(const char *label, const Benchmark &bench, const Benchmark &parent)
		{
			float x_h = x;
			render.Write(*font[0], label, x_h, y, config, 1, &title_color);

			float x_a = x + col_a_x;
			render.Write(*font[0], String::Format("%0.02fms", bench.GetMs()), x_a, y, config, 1, &title_color);
			float x_b = x + col_b_x;
			render.Write(*font[0], String::Format("%d%%", parent.GetMs() ? int(bench.GetMs() * 100.f / parent.GetMs()) : 0), x_b, y, config, 1, &title_color);

			render.Write(*font[0], "\n", x, y, config, 1, &title_color);
		}
		void		RenderSystem(const Profiler::System *sys, const Profiler::System *parent, int indent_level)
		{
			float x_s = x;
			x += indent_level * indent_width;

			if	(parent)
					DisplaySystem(sys->label, sys->profile, parent->profile);
			else	DisplaySystem(sys->label, sys->profile);

			x = x_s;

			ListForeachPtr(Profiler::System *, sub, sys->sub_systems)
				RenderSystem(sub, sys, indent_level + 1);
		}

public:

		void		DisplayHeader(const char *header)
		{
			render.Write(*font[1], String(header) << "\n\n", x, y, config, 1, &title_color);
		}

		void		StartRender()
		{
			render.SetWorldMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix());
			render.SetViewMatrix(Matrix4::IdentityMatrix(), &Matrix4::IdentityMatrix());
			render.SetProjectionMatrix(Matrix4::IdentityMatrix());
		}
		void		Render(const Profiler &profiler)
		{
			ListForeachPtr(Profiler::System *, sys, profiler.root_systems)
				RenderSystem(sys, NULL, 0);
		}

		ProfilerRenderer(Renderer &r, RasterFont *f[2], float &_x, float &_y) : render(r), font(f), x(_x), y(_y), config(false), title_color(1, 1, 1) {}
};

} // GS

//------------------------------------------------------------------------------
void		SceneProfiler::ResetProfiles()
{
	Profiler::ResetProfiles();
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void		Scene::DrawProfilerText(Renderer &render, RasterFont *font[2], float &x, float &y)
{
	ProfilerRenderer prof_render(render, font, x, y);

	prof_render.StartRender();
	prof_render.DisplayHeader(String::Format("Scene: %d item, %d active (%d%%)", item_list.GetCount(), active_list.GetCount(), item_list.GetCount() ? (active_list.GetCount() * 100) / item_list.GetCount() : 100));
	prof_render.Render(profiler);
}
//------------------------------------------------------------------------------
