// core
#include "Core/Asura.h"

// header
#include "Core/Profile/AVP_Profile_Graphics.h"

// ASURA
#include "Camera/Asura_Camera.h"
#include "Core/Asura_HashedLocalisedText.h"
#include "Core/Asura_Timers.h"
#include "GUIMenu/Asura_GUIMenu_Element_Text.h"
#include "GUIMenu/Asura_GUIMenu_Menu_Page.h"
#include "GUIMenu/Asura_GUIMenu_System.h"
#include "Rendering/Asura_Direct3D_UserOptions.h"


// AVP
#include "Core/AVP_Settings.h"

void AVP_Profile_Graphics::Platform_SetToDefaults()
{
	m_uVisualQuality	      = Asura_Direct3D_UserOptions::BASIC_SETTING_HIGH;
	m_uTextureQuality	      = Asura_Direct3D_UserOptions::BASIC_SETTING_HIGH;
	m_uShadowQuality	      = Asura_Direct3D_UserOptions::BASIC_SETTING_HIGH;
	m_uAntiAliasing			  = 2;
	m_uResolutionIndex        = 0;	
	m_uOldResolutionIndex     = 0;
	m_bTrilinearFiltering     = true;
	m_fGamma                  = 0.5f;
	m_uAnisotropicFiltering   = Asura_Direct3D_UserOptions::GetMaxAnisotropySetting();
	m_uNewResConfirmationTimer= CONFIRMATION_TIME_LENGTH;
}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_AcceptNewRes( bool bHelp)
{
	if( bHelp)
	{
		Asura_CommandConsole::Printf("Accepts the new PC resolution selected from options.");
		return true;
	}
	else
	{
		//s_uOldResolutionIndex = s_uResolutionIndex;
		
		// close current page to keep menu stack tidy and free before opening the next page. 
		Asura_GUIMenu_System::CloseMenuPage( Asura_GUIMenu_System::GetFocusedMenuHashID() );
		// on a resolution accept we go back to the graphics options page.
		Asura_GUIMenu_System::SetFocusedMenuByID( GetCurSpeciesGraphicsMenuHash());
	}

	return false;

}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_ChangeVisualDetails( bool bHelp)
{
	if( bHelp )
	{
		Asura_CommandConsole::Printf(L"Steps to the next visual detail setting.\n");
		return false;
	}
	else
	{
		AVP_Profile_Graphics& xCurPrfGfx = AVP_Settings::GetCurrentProfile()->GetGraphics();

		++xCurPrfGfx.m_uVisualQuality;
		if( xCurPrfGfx.m_uVisualQuality == 1)
		{
			xCurPrfGfx.m_uVisualQuality++;
		}
		xCurPrfGfx.m_uVisualQuality %= Asura_Direct3D_UserOptions::BASIC_SETTING_CUSTOM; // Max value is 2 Asura_Direct3D_UserOptions::BASIC_SETTING_CUSTOM;
	}

	return false;
}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_ChangeTextureDetails( bool bHelp)
{
	if( bHelp )
	{
		Asura_CommandConsole::Printf(L"Steps to the next texture detail setting.\n");
		return false;
	}
	else
	{
		AVP_Profile_Graphics& xCurPrfGfx = AVP_Settings::GetCurrentProfile()->GetGraphics();

		++xCurPrfGfx.m_uTextureQuality;
		xCurPrfGfx.m_uTextureQuality %= Asura_Direct3D_UserOptions::BASIC_SETTING_CUSTOM;
	}

	return false;
}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_ChangeShadowDetails( bool bHelp)
{
	if( bHelp )
	{
		Asura_CommandConsole::Printf(L"Steps to the next shadow detail setting.\n");
		return false;
	}
	else
	{
		AVP_Profile_Graphics& xCurPrfGfx = AVP_Settings::GetCurrentProfile()->GetGraphics();

		++xCurPrfGfx.m_uShadowQuality;
		xCurPrfGfx.m_uShadowQuality %= Asura_Direct3D_UserOptions::BASIC_SETTING_CUSTOM;
	}

	return false;
}


bool AVP_Profile_Graphics::Platform_ConsoleCmd_ChangeResolution( u_int uResIndex, bool bInterrogate, bool bHelp )
{
	if (bInterrogate || bHelp)
	{
		Asura_CommandConsole::Printf("selects Resolutions from menu");
		return true;
	}
	else
	{
		AVP_Profile_Graphics& xCurPrfGfx = AVP_Settings::GetCurrentProfile()->GetGraphics();

		xCurPrfGfx.m_uOldResolutionIndex = xCurPrfGfx.m_uResolutionIndex;
		xCurPrfGfx.m_uResolutionIndex    = uResIndex;

		// close current page to keep menu stack tidy and free before opening the next page. 
		Asura_GUIMenu_System::CloseMenuPage( Asura_GUIMenu_System::GetFocusedMenuHashID() );
		Asura_GUIMenu_System::OpenMenuPage( GetCurSpeciesConfirmResMenuHash(), true, false);

		return Platform_SetResolution(uResIndex);
	}
}


bool AVP_Profile_Graphics::Platform_ConsoleCmd_RevertResolution(bool bHelp )
{
	if (bHelp)
	{
		Asura_CommandConsole::Printf("reverts to the previous PC resolution.");
		return true;
	}
	else
	{
		AVP_Profile_Graphics& xCurPrfGfx = AVP_Settings::GetCurrentProfile()->GetGraphics();

		xCurPrfGfx.m_uNewResConfirmationTimer = CONFIRMATION_TIME_LENGTH;
		xCurPrfGfx.m_uResolutionIndex         = xCurPrfGfx.m_uOldResolutionIndex;

		// close current page to keep menu stack tidy and free before opening the next page. 
		Asura_GUIMenu_System::CloseMenuPage( Asura_GUIMenu_System::GetFocusedMenuHashID() );
		// on a resolution revert we go back to the resolution selection page.
		Asura_GUIMenu_System::OpenMenuPage( GetCurSpeciesResolutionsMenuHash(), true, false);

		return Platform_SetResolution(xCurPrfGfx.m_uOldResolutionIndex);
	}
}

bool AVP_Profile_Graphics::Platform_SetResolution(u_int uResIndex)
{
	const Asura_List<Asura_Direct3D_UserOptions::ResolutionInfo>* pxList = Asura_Direct3D_UserOptions::GetSupportedResolutions(0);
	u_int uEntry = 0; 
	Asura_List_ConstIt<Asura_Direct3D_UserOptions::ResolutionInfo> xIt(pxList);
	while(!xIt.Done())
	{
		if (xIt.GetCurrent()->m_xModeData.Width >= 800
			&& xIt.GetCurrent()->m_xModeData.Height >= 600)
		{
			if (uEntry == uResIndex)
			{

				Asura_Render::SetVideoMode( xIt.GetCurrent()->m_xModeData.Width, xIt.GetCurrent()->m_xModeData.Height, false);
				Asura_Camera::SetPhysicalScreenAspectRatio( static_cast<float>(xIt.GetCurrent()->m_xModeData.Width) / static_cast<float>(xIt.GetCurrent()->m_xModeData.Height) );
				return true;	
			}
			++uEntry;
		}			
		xIt.Next();
	}
	return false;
}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_ResolutionsList( u_int uResIndex, bool bInterrogate, bool bHelp )
{
	if (bInterrogate || bHelp)
	{
		Asura_CommandConsole::Printf("Lists Resolutions for menu");
		return true;
	}
	else
	{
		const Asura_List<Asura_Direct3D_UserOptions::ResolutionInfo>* pxList = Asura_Direct3D_UserOptions::GetSupportedResolutions(0);
		u_int uEntry = 0; 
		Asura_List_ConstIt<Asura_Direct3D_UserOptions::ResolutionInfo> xIt(pxList);
		while(!xIt.Done())
		{
			if (xIt.GetCurrent()->m_xModeData.Width >= 800
				&& xIt.GetCurrent()->m_xModeData.Height >= 600)
			{
				if (uEntry == uResIndex)
				{
					Asura_CommandConsole::Printf(L"%u x %u", xIt.GetCurrent()->m_xModeData.Width, xIt.GetCurrent()->m_xModeData.Height);
					return true;
				}
				++uEntry;
			}			
			xIt.Next();
		}
	}

	return false;
}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_ChangeAnisotropicFilteringRight(bool bHelp)
{
	if( bHelp )
	{
		Asura_CommandConsole::Printf(L"Steps to the next anisotropic setting thats available.\n");
		return false;
	}
	else
	{
		Platform_ChangeAnisotropicFiltering(1);
		return false;
	}
}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_ChangeAnisotropicFilteringLeft(bool bHelp)
{
	if( bHelp )
	{
		Asura_CommandConsole::Printf(L"Steps to the next anisotropic setting thats available.\n");
		return false;
	}
	else
	{
		Platform_ChangeAnisotropicFiltering(-1);
		return false;
	}
}

void AVP_Profile_Graphics::Platform_ChangeAnisotropicFiltering(int iStep)
{
	AVP_Profile_Graphics& xCurPrfGfx = AVP_Settings::GetCurrentProfile()->GetGraphics();

	if(xCurPrfGfx.m_uAnisotropicFiltering == 0)
	{
		if(iStep == -1)
		{
			xCurPrfGfx.m_uAnisotropicFiltering = Asura_Direct3D_UserOptions::GetMaxAnisotropySetting() + 1;
		}
		else
		{
			xCurPrfGfx.m_uAnisotropicFiltering += iStep;
		}

	}
	xCurPrfGfx.m_uAnisotropicFiltering += iStep;
	xCurPrfGfx.m_uAnisotropicFiltering     %= (Asura_Direct3D_UserOptions::GetMaxAnisotropySetting() + 1);

	if( xCurPrfGfx.m_uAnisotropicFiltering == 1)
	{
		xCurPrfGfx.m_uAnisotropicFiltering += iStep;
	}
	Platform_UpdateAnisotropicFilteringDynLbl(xCurPrfGfx.m_uAnisotropicFiltering);
}

bool AVP_Profile_Graphics::Platform_ConsoleCmd_OnInitGraphicsOptions( bool bHelp)
{
	Platform_UpdateAnisotropicFilteringDynLbl(AVP_Settings::GetCurrentProfile()->GetGraphics().m_uAnisotropicFiltering);
	return true;
}

void AVP_Profile_Graphics::Platform_UpdateAnisotropicFilteringDynLbl(u_int uAnisotropicFiltering)
{
	Asura_GUIMenu_Menu_Page* pxPage = Asura_GUIMenu_System::GetMenuPageByID( GetCurSpeciesGraphicsMenuHash() );
	if( pxPage)
	{
		Asura_GUIMenu_Element_Text* pxText = static_cast<Asura_GUIMenu_Element_Text*>(pxPage->FindContainerItemByLocalNameHash(s_uAVP_PROFILE_DYN_FILETRING_LBL));
		if( pxText)
		{
			Asura_UnicodeChar wszBuffer[64];
			if( uAnisotropicFiltering != 0)
			{
				Asura_PrintfToBfr( wszBuffer, L"%d : 1", 16, true, uAnisotropicFiltering);
			}
			else
			{
				wcscpy( wszBuffer, Asura_HashedLocalisedText::GetString( uASURA_HASHEDTEXTPAGE_MENU, s_uAVP_PROFILE_OFF_CAPTION));
			}

			pxText->SetText( wszBuffer);
		}
	}
}

void AVP_Profile_Graphics::Platform_UpdateNewResConfirmationTimer()
{
	static float fNewResConfirmationTimer = CONFIRMATION_TIME_LENGTH;

	// controls the timer on the resolution confirmation screen.
	if( Asura_GUIMenu_System::IsMenuPageHashActive( GetCurSpeciesConfirmResMenuHash() ) )
	{

		fNewResConfirmationTimer -= Asura_Timers::GetActualFrameTime();	

		AVP_Profile_Graphics& xCurPrfGfx = AVP_Settings::GetCurrentProfile()->GetGraphics();

		xCurPrfGfx.m_uNewResConfirmationTimer = static_cast<int> ( fNewResConfirmationTimer );
		if( xCurPrfGfx.m_uNewResConfirmationTimer <= 0)
		{
			xCurPrfGfx.m_uNewResConfirmationTimer = 0;
			Platform_ConsoleCmd_RevertResolution( false );
		}
	}
	else
	{
		fNewResConfirmationTimer = CONFIRMATION_TIME_LENGTH;
	}
}

void AVP_Profile_Graphics::Platform_ApplySettings()
{
	Asura_Direct3D_UserOptions::SetGammaSetting( m_fGamma );
}