//*******************************************************************
//
// File: Tools_Botanicals_Statistics.cpp     
//
// Created: 16 Mar 2006
//
// Description: 
//
//*******************************************************************

// system libraries
#include "Core/Asura.h"

#if defined( ASURA_USE_BOTANICALS) && defined( ASURA_TOOLS)

// main header
#include "Tools_Botanicals_Statistics.h"

// other libraries
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render.h"
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render_Manager.h"

#include "Camera/Asura_Camera.h"

#include "Core/Asura_Timers.h"

#include "Rendering/Asura_Render.h"
#include "Rendering/Asura_Text_Output.h"
#include "Rendering/Asura_Viewport.h"

// internal dependencies
#include "Misc/Tools_CyclicBuffer.h"

//*******************************************************************
// Constants
//*******************************************************************


//*******************************************************************
// Local Classes
//*******************************************************************

//*******************************************************************
// Static Data
//*******************************************************************

float Tools_Botanicals_Statistics::s_fTime = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIP3DCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPLeafCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPImposterCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPIndexCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPVertexCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPPrimitiveCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPLeafPrimitiveCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIP3DPrimitiveCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDIPImposterPrimitiveCount = 0;
uint32 Tools_Botanicals_Statistics::s_uInstanceCount = 0;

uint32 Tools_Botanicals_Statistics::s_uDynamicLightTotalCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDynamicLightVertexCount = 0;
uint32 Tools_Botanicals_Statistics::s_uDynamicLightObjectCount = 0;


static LARGE_INTEGER g_xBotanicalQPCFrameTimeLast = {0};
static LARGE_INTEGER g_xBotanicalQPF = {0};

static Tools_CyclicBuffer< float> g_BotanicalTimeAverage( 128);
static Tools_CyclicBuffer< LONGLONG> g_BotanicalQPCFrameTimeAverage( 128);

//*******************************************************************
// Function Definitions
//*******************************************************************


bool Tools_Botanicals_Statistics::Reset()
{
	s_fTime = 0;
	s_uDIPCount = 0;
	s_uDIP3DCount = 0;
	s_uDIPLeafCount = 0;
	s_uDIPImposterCount = 0;
	s_uDIPIndexCount = 0;
	s_uDIPVertexCount = 0;
	s_uDIPPrimitiveCount = 0;
	s_uDIP3DPrimitiveCount = 0;
	s_uDIPLeafPrimitiveCount = 0;
	s_uDIPImposterPrimitiveCount = 0;
	s_uInstanceCount = 0;
	s_uDynamicLightTotalCount = 0;
	s_uDynamicLightVertexCount = 0;
	s_uDynamicLightObjectCount = 0;
	return( true);
}

bool Tools_Botanicals_Statistics::Render()
{
	{
		if( 0 == g_xBotanicalQPF.QuadPart)
		{
			QueryPerformanceFrequency( &g_xBotanicalQPF);
		}
		LARGE_INTEGER xBotanicalQPCFrameTimeNow;
		
		QueryPerformanceCounter( &xBotanicalQPCFrameTimeNow);
		
		LONGLONG xBotanicalQPCFrameTimeDelta = xBotanicalQPCFrameTimeNow.QuadPart - g_xBotanicalQPCFrameTimeLast.QuadPart;

		g_BotanicalQPCFrameTimeAverage.ValueAdd( xBotanicalQPCFrameTimeDelta);
		
		g_xBotanicalQPCFrameTimeLast = xBotanicalQPCFrameTimeNow;
	}

	const bool bBGRHasDataSet = Asura_Direct3D_Botanicals_Game_Render::HasDataSet();
	const Asura_Direct3D_BGR_Manager& xBGRManager = Asura_Direct3D_Botanicals_Game_Render::GetDirect3DBGRManager();
	const float fWindowWidth = 500;
	const float fWindowX = Asura_Viewport::GetWidth() - fWindowWidth;
	float printx;
	float printy;
	int colour = 0xff50ff90;

	Asura_Render::CurrentStates.RequestAlphaTest( false);
	
//	{
		//determine print position
		//float width = (float)Asura_Viewport::GetWidth();
		float width = fWindowX;
		float height = (float)Asura_Viewport::GetHeight();
		Asura_Text_Output::ConvertPixelsToPrintCoords(width,height);
		//printx = width-35;
		printx = width + 1;
		printy = 2;
//	}

	float fCursorInfoHeightInChars = 16;
	
	if( true == bBGRHasDataSet)
	{
		const uint32 uTypeCount = xBGRManager.m_xArray_xTypes.Size();
		
		fCursorInfoHeightInChars += 1;
		fCursorInfoHeightInChars += uTypeCount / 2;
	}
	
	const float fLineHeight = fCursorInfoHeightInChars;
	//draw a translucent polygon as a background
	Asura_Render::Overlay.SetRectXY( fWindowX, 1*fLineHeight, fWindowWidth, fCursorInfoHeightInChars * fLineHeight);
	Asura_Render::Overlay.SetRectUV( 0, 0, 1, 1);
	Asura_Render::Overlay.TranslucencyMode = ASURA_TRANSLUCENCY_NORMAL;
	Asura_Render::Overlay.TextureIndex = ASURA_TEXTURE_NONE;
	Asura_Render::Overlay.Colour=0x4f000000;
	Asura_Render::Overlay.Render();
	Asura_Render::FlushDisplay();

	Asura_Text_Output::Print(printx,printy++,colour,0,"Botanical Statistics:");
	Asura_Text_Output::Print(printx,printy++,colour,0,"BGR: %s", (true == bBGRHasDataSet ? "Active" : "Deactive"));

	float fAverageFrameTime = static_cast< float>( g_BotanicalQPCFrameTimeAverage.GetAverage() * (1000.0 / static_cast< double>( g_xBotanicalQPF.QuadPart)));
	float fPresentFrameTime = static_cast< float>( g_BotanicalQPCFrameTimeAverage.GetPresent() * (1000.0 / static_cast< double>( g_xBotanicalQPF.QuadPart)));
	Asura_Text_Output::Print(printx,printy++,colour,0,"Frame %f ms (%f) ms", fPresentFrameTime, fAverageFrameTime);
	
	{
		const float fTime = 1000.0f * s_fTime;
		g_BotanicalTimeAverage.ValueAdd( fTime);
		const float fTimeAverage = g_BotanicalTimeAverage.GetAverage();
		Asura_Text_Output::Print(printx,printy++,colour,0,"Time %f ms (%f) ms", fTime, fTimeAverage);
	}
	
	Asura_Text_Output::Print(printx,printy++,colour,0,"DIP C %6d B %6d L %6d I %6d", s_uDIPCount, s_uDIP3DCount, s_uDIPLeafCount, s_uDIPImposterCount);
	Asura_Text_Output::Print(printx,printy++,colour,0,"DIP P %6d B %6d L %6d I %6d", s_uDIPPrimitiveCount, s_uDIP3DPrimitiveCount, s_uDIPLeafPrimitiveCount, s_uDIPImposterPrimitiveCount);
	Asura_Text_Output::Print(printx,printy++,colour,0,"DIP I %d", s_uDIPIndexCount);
	Asura_Text_Output::Print(printx,printy++,colour,0,"DIP V %d", s_uDIPVertexCount);
	Asura_Text_Output::Print(printx,printy++,colour,0,"Instances %d", s_uInstanceCount);
	
	Asura_Text_Output::Print(printx,printy++,colour,0,"V/P %f", static_cast<float>( static_cast< double>( s_uDIPVertexCount) / static_cast< double>( s_uDIPPrimitiveCount)));
	Asura_Text_Output::Print(printx,printy++,colour,0,"MP/s %f", static_cast<float>( s_uDIPPrimitiveCount / (1e6 * g_BotanicalQPCFrameTimeAverage.GetAverage() / static_cast< double>( g_xBotanicalQPF.QuadPart))));
	
	printy++;
	
	Asura_Text_Output::Print(printx,printy++,colour,0,"Dynamic %d %d %d", s_uDynamicLightTotalCount, s_uDynamicLightObjectCount, s_uDynamicLightVertexCount);
	
	printy++;
	
	if( true == bBGRHasDataSet)
	{
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
		{
			uint32 uVertexBytes;
			uint32 uIndexBytes;
			
			xBGRManager.m_xD3DBuffer3DGeomtery.GetBufferBytes( uVertexBytes, uIndexBytes);
			
			Asura_Text_Output::Print(printx,printy++,colour,0,"3D V %d I %d", xBGRManager.m_xD3DBuffer3DGeomtery.m_uVBSize, xBGRManager.m_xD3DBuffer3DGeomtery.m_uIBSize);	
			Asura_Text_Output::Print(printx,printy++,colour,0,"3D V %d b I %d b", uVertexBytes, uIndexBytes);	
		}
#endif
		
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
		Asura_Text_Output::Print(printx,printy++,colour,0,"Lf V %d I %d", xBGRManager.m_xD3DBuffer3DLeaves.m_uVBSize, xBGRManager.m_xD3DBuffer3DLeaves.m_uIBSize);	
#endif
		
		//Asura_Text_Output::GetSmallFontHandle()
		const uint32 uTypeCount = xBGRManager.m_xArray_xTypes.Size();
		for( uint32 uTypeIndex = 0; uTypeIndex < uTypeCount; uTypeIndex += 1)
		{
			const Asura_Direct3D_BGR_Type& xType = xBGRManager.m_xArray_xTypes[ uTypeIndex];
			
			u_int uBranchCount = 0;
			u_int uFrondCount = 0;
			u_int uLeafCount = 0;
			u_int uImposterCount = 0;
			
			u_int uSectionCount = xType.m_xArray_xSections.Size();
			for( u_int uSectionIndex = 0; uSectionIndex < uSectionCount; uSectionIndex += 1)
			{
				const Asura_Direct3D_BGR_Section& xSection = xType.m_xArray_xSections[ uSectionIndex];
				
				u_int uSectionVersionCount = xSection.m_xArray_xVersions.Size();
				for( u_int uSectionVersionIndex = 0; uSectionVersionIndex < uSectionVersionCount; uSectionVersionIndex += 1)
				{
					const Asura_Direct3D_BGR_Section_Version& xSectionVersion = xSection.m_xArray_xVersions[ uSectionVersionIndex];
					const Asura_Direct3D_BGR_Geometry& xGeometry = xSectionVersion.m_xGeometry;
					
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
					uBranchCount = xGeometry.m_xArrayBranchs.Size();
					uFrondCount = xGeometry.m_xArrayFronds.Size();
#endif
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
					uLeafCount = xGeometry.m_xArrayLeaves.Size();
#endif
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
					uImposterCount = xGeometry.m_xArrayBillboards.Size();
#endif
				}
			}
			const u_int uInstanceMaxCount = xType.m_uInstanceMaxCount;
			
			Asura_Text_Output::Print(printx,printy++,colour,ASURA_TEXT_FORMAT_SMALLFONT,"%3d B %d F %d L %d I %d Inst %4d '%s'", xType.GetType().GetID(), uBranchCount, uFrondCount, uLeafCount, uImposterCount, uInstanceMaxCount, xType.m_xName.GetString());
		}
	}
	
	return( true);
}



//*******************************************************************
//
// (c) 2006 Rebellion (Derby)
//
// Warning: This computer program is protected by copyright law and 
// international treaties. Unauthorized reproduction or distribution
// of this program, or any portion of it, may result in severe civil and
// criminal penalties, and will be prosecuted to the maximum extent 
// possible under the law.
//
//*******************************************************************

#endif //defined( ASURA_USE_BOTANICALS) && defined( ASURA_TOOLS)
