// Example showing how to use the profiler
//
// Button			Function
// =====================================================
// A					Enable/Disable Bar Graphs
// B					Enable/Disable Text Values
// X					Enable/Disable History Graph
// Y					Switch graph time between global, set by maximum render time
//						and individual times, set by each probles maximum time
// UP					Reduce rows displayed on page
// DOWN				Increase rows displayed on page
// LEFT				Back Page
// RIGHT			Next Page


#include "profiler-test.hpp"
#include "graphics/color.hpp"
#include "engine/profiler.hpp"
#include <cmath>

using namespace blit;

#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240

Profiler 			g_profiler; // global uRunningAverageSize and uRunningAverageSpan could be set here.
ProfilerProbe *g_pRenderProbe;
ProfilerProbe *g_pClearProbe;
ProfilerProbe *g_pRectProbe;
ProfilerProbe *g_pCircleProbe;
ProfilerProbe *g_pUpdateProbe;


uint32_t g_uSize = 2;
uint32_t g_uSizeMax	= SCREEN_HEIGHT-1;
uint32_t g_uSizeMin	= 2;
int g_uSizeChange = 1;

bool g_bGraphEnabled   = true;
bool g_bLabelsEnabled  = true;
bool g_bDisplayHistory = true;
bool g_bUseGlobalTime	 = true;

uint8_t g_uRows = 5;
uint8_t g_uPage = 1;



#define RANDX random()%SCREEN_WIDTH
#define RANDY random()%SCREEN_HEIGHT
#define RANDC (int)(random()%256)

void SetupMetrics()
{
	g_profiler.setup_graph_element(Profiler::dmCur, g_bLabelsEnabled, g_bGraphEnabled, Pen(0,255,0));
	g_profiler.setup_graph_element(Profiler::dmAvg, g_bLabelsEnabled, g_bGraphEnabled, Pen(0,255,255));
	g_profiler.setup_graph_element(Profiler::dmMax, g_bLabelsEnabled, g_bGraphEnabled, Pen(255,0,0));
	g_profiler.setup_graph_element(Profiler::dmMin, g_bLabelsEnabled, g_bGraphEnabled, Pen(255,255,0));
}

void init()
{
	set_screen_mode(ScreenMode::hires);

	// set up profiler
	g_profiler.set_display_size(SCREEN_WIDTH, SCREEN_HEIGHT);
	g_profiler.set_rows(g_uRows);
	g_profiler.set_alpha(200);
	g_profiler.display_history(g_bDisplayHistory);

	// create probes
	g_pRenderProbe 	= g_profiler.add_probe("Render", 300); 	// 300 frames of history
	g_pClearProbe 	= g_profiler.add_probe("Clear", 50, 6); 	// Example of lower resolution, 50 samples with a span of 6 = 300 frames
	g_pRectProbe 		= g_profiler.add_probe("Rectangle", 300);
	g_pCircleProbe 	= g_profiler.add_probe("Circle", 300);
	g_pUpdateProbe 	= g_profiler.add_probe("Update");

	// enable metrics
	SetupMetrics();
}


void render(uint32_t time)
{
	static Point    ptMiddle(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);

	//static ProfilerProbe *pAwayRenderProbe = g_profiler.AddProbe("AwayFromRender");


	//pAwayRenderProbe->StoreElapsedUs(true);

	bool button_a = buttons.pressed & Button::A;
	bool button_b = buttons.pressed & Button::B;
	bool button_x = buttons.pressed & Button::X;
	bool button_y = buttons.pressed & Button::Y;
	bool button_up = buttons.pressed & Button::DPAD_UP;
	bool button_down = buttons.pressed & Button::DPAD_DOWN;
	bool button_left = buttons.pressed & Button::DPAD_LEFT;
	bool button_right = buttons.pressed & Button::DPAD_RIGHT;
	bool button_home = buttons.pressed & Button::HOME;

	if(button_up && (g_uRows>1))
	{
		g_uRows --;
		g_profiler.set_rows(g_uRows);
	}

	if(button_down && (g_uRows<11))
	{
		g_uRows ++;
		g_profiler.set_rows(g_uRows);
	}

	if(button_left && (g_uPage > 1))
	{
		g_uPage--;
	}

	if(button_right && (g_uPage < g_profiler.get_page_count()))
	{
		g_uPage++;
	}

	if(button_a)
	{
		// Graphs
		g_bGraphEnabled = !g_bGraphEnabled;
		SetupMetrics();
	}


	if(button_b)
	{
		// Graphs
		g_bLabelsEnabled = !g_bLabelsEnabled;
		SetupMetrics();
	}

	if(button_x)
	{
		// Graphs
		g_bDisplayHistory = !g_bDisplayHistory;
		g_profiler.display_history(g_bDisplayHistory);
	}

	if(button_y)
	{
		// change Graphs from time set globally to time set locally
		g_bUseGlobalTime = !g_bUseGlobalTime;
	}

	if(button_home)
	{
		// Log to CDC current values
		g_profiler.log_probes();
	}

	g_pRenderProbe->start();

	// clear screen
	g_pClearProbe->start();
  screen.pen = Pen(0, 0, 0, 255);
  screen.clear();
  g_pClearProbe->store_elapsed_us();

  // draw rect
  g_pRectProbe->start();
 	screen.pen = Pen(0,0,255,255);
 	Point ptTl = Point(ptMiddle.x-(g_uSize/2), ptMiddle.y-(g_uSize/2));
 	Point ptBr = Point(ptMiddle.x+(g_uSize/2), ptMiddle.y+(g_uSize/2));
  screen.rectangle(Rect(ptTl, ptBr));
  g_pRectProbe->store_elapsed_us();

  // draw circle
  g_pCircleProbe->start();
 	screen.pen = Pen(255,0,0,128);
  screen.circle(ptMiddle, (g_uSizeMax-g_uSize)/2);
  g_pCircleProbe->store_elapsed_us();


  g_pRenderProbe->store_elapsed_us();

  if(g_bUseGlobalTime)
  {
    // set global graph time to maximum render time
  	g_profiler.set_graph_time(g_pRenderProbe->elapsed_metrics().uMaxElapsedUs);
  }
  else
  {
    // disable global graph time
  	g_profiler.set_graph_time(0);

  	// set All probes graph time to their maximum logged value
  	g_pRenderProbe->set_graph_time_us_to_max();;
  	g_pClearProbe->set_graph_time_us_to_max();;
  	g_pRectProbe->set_graph_time_us_to_max();;
  	g_pCircleProbe->set_graph_time_us_to_max();;
  	g_pUpdateProbe->set_graph_time_us_to_max();;
  }

  // display the overlay
  g_profiler.display_probe_overlay(g_uPage);

}

void update(uint32_t time)
{
	// Scoped profiler probes automatically call Start() and at end of scope call StoreElapsedUs()
	ScopedProfilerProbe scopedProbe(g_pUpdateProbe);

  g_uSize+=g_uSizeChange;
  if(g_uSize >= g_uSizeMax)
  {
  	g_uSize -= (g_uSize-g_uSizeMax);
  	g_uSizeChange = - g_uSizeChange;
  }
  else
  {
    if(g_uSize <= g_uSizeMin)
    {
    	g_uSize += g_uSizeMin-g_uSize;
    	g_uSizeChange = - g_uSizeChange;
    }
  }

}
