//
// Tools_EffectVolume_FogOverlay.cpp
//
// Created by Emil Popovic - 12/01/2009
// 
// Copyright (C) 2009 Rebellion, All Rights Reserved.
//

//////////////////////////////////////////////////////////////////////////////
//
// includes
//
//////////////////////////////////////////////////////////////////////////////

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

// header
#include "Entity/EffectVolume/Tools_EffectVolume_FogOverlay.h"

// asura
#include "Core/Asura_UserInput.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Tools_ColourPicker.h"
#include "Interface/Asura_Graph_Dialog.h"

// tools
#include "Tools_System.h"
#include "Misc/Tools_Modal_Overlay.h"



static const float fMIN_VALUE_FOR_FOG_AT_FAR_PLANE = 5.0f;



bool	Tools_EffectVolume_FogOverlay::s_bChangedFogOverlay = false;
bool	Tools_EffectVolume_FogOverlay::s_bGraphFogEnabled = true;
float	Tools_EffectVolume_FogOverlay::s_fSkyboxFogBlendFactor;
bool	Tools_EffectVolume_FogOverlay::s_bMadeChanges = false;
float	Tools_EffectVolume_FogOverlay::s_fFogRed;
float	Tools_EffectVolume_FogOverlay::s_fFogGreen;
float	Tools_EffectVolume_FogOverlay::s_fFogBlue;
bool	Tools_EffectVolume_FogOverlay::s_bChangedMinFog = false;
bool	Tools_EffectVolume_FogOverlay::s_bChangedMaxFog = false;
float	Tools_EffectVolume_FogOverlay::s_fFogNearPlane;
float	Tools_EffectVolume_FogOverlay::s_fFogFarPlane;
float	Tools_EffectVolume_FogOverlay::s_fFogValueAtFarPlane = fMIN_VALUE_FOR_FOG_AT_FAR_PLANE;
Asura_Graph<float>* Tools_EffectVolume_FogOverlay::s_pxFogDensityGraph = NULL;




Tools_EffectVolume_FogOverlay::Tools_EffectVolume_FogOverlay ( Asura_Fog_Parameters& xFogParameters )
:Tools_Modal_Overlay("Modify Fog Values")
, m_xFogParameters( xFogParameters )
, m_bReturnValue( false )
{
	s_fSkyboxFogBlendFactor	= xFogParameters.GetSkyboxFogBlendFactor()*100.0f;	// Blend factor is from 0.0f to 1.0f ... But our gui, is from 0 to 100 (consider it as %)

	s_bGraphFogEnabled		= xFogParameters.IsGraphFogEnabled();
	s_fFogRed				= xFogParameters.GetFogColour().m_fR;
	s_fFogGreen				= xFogParameters.GetFogColour().m_fG;
	s_fFogBlue				= xFogParameters.GetFogColour().m_fB;

	s_fFogNearPlane			= xFogParameters.GetFogNearPlane();
	s_fFogFarPlane			= xFogParameters.GetFogFarPlane();

	s_fFogValueAtFarPlane	= Asura_Maths::Max( xFogParameters.GetFogValueAtFarPlane()* 100.0f, fMIN_VALUE_FOR_FOG_AT_FAR_PLANE );	// Value cannot be smaller that fMIN_VALUE_FOR_FOG_AT_FAR_PLANE

	s_pxFogDensityGraph		= new Asura_Graph<float>(2, 0.0f, xFogParameters.GetFogValueAtFarPlane());
	Asura_Vector_2 xGraphPoint = xFogParameters.GetGraphFogPoint();
	s_pxFogDensityGraph->AddPoint(xGraphPoint.y, xGraphPoint.x);


	s_bMadeChanges			= false;
	s_bChangedMinFog		= false;
	s_bChangedMaxFog		= false;
	s_bChangedFogOverlay	= false;
}

Tools_EffectVolume_FogOverlay ::~Tools_EffectVolume_FogOverlay ()
{
	delete s_pxFogDensityGraph;
	s_pxFogDensityGraph = NULL;
}

void Tools_EffectVolume_FogOverlay ::WriteNewValuesToFogParameters( Asura_Fog_Parameters& xFogParameters )
{
	xFogParameters.SetFogColour( s_fFogRed, s_fFogGreen, s_fFogBlue );
	xFogParameters.SetFogNearPlane( s_fFogNearPlane );
	xFogParameters.SetFogFarPlane( s_fFogFarPlane );
	xFogParameters.SetSkyboxFogBlendFactor( s_fSkyboxFogBlendFactor/100.0f );	// 	// Blend factor is from 0.0f to 1.0f ... But our gui, is from 0 to 100 (consider it as %)

	if (s_bGraphFogEnabled)
	{
		xFogParameters.SetFogValueAtFarPlane( s_pxFogDensityGraph->GetValueAtTime(1.0f) );
	}
	else
	{
		xFogParameters.SetFogValueAtFarPlane( s_fFogValueAtFarPlane/100.0f );
	}


	xFogParameters.EnableGraphFog(s_bGraphFogEnabled);

	Asura_Vector_2 xGraphFogPoint;
	xGraphFogPoint.x = s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_fTime;
	xGraphFogPoint.y = s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_xValue;
	xFogParameters.SetGraphFogPoint(xGraphFogPoint);
}


void Tools_EffectVolume_FogOverlay ::InitialiseOverlay(class Asura_Overlay* pxOverlay)
{
	Asura_Dialog* pxDialog = NULL;

	Asura_Vector_2 xOffset = Asura_Vector_2(1.0f,3.0f);

	pxDialog = new Asura_Numerical_Dialog( "Skybox fogging (%)", xOffset, &s_fSkyboxFogBlendFactor, 0.0f, 100.0f, 1.0f, "%3.0f", &s_bMadeChanges );
	pxOverlay->AddDialog(pxDialog);
	// render colours to one side of previous menu items
	const float fLeftDialogsWidth = 24.0f;
	xOffset.x += fLeftDialogsWidth;

	//insert colour selection box below
	Tools_ColourPicker_Dialog* pxFogColourPickerDialog = new Tools_ColourPicker_Dialog("Fog Colour",xOffset,Asura_Vector_2(4.0f,3.0f),&s_fFogRed,&s_fFogGreen,&s_fFogBlue,1.0f,&s_bMadeChanges);
	pxFogColourPickerDialog->EnableHDR(true);
	pxFogColourPickerDialog->SetHelpText("Fog Colour");
	pxOverlay->AddDialog(pxFogColourPickerDialog);

	// move the offset back to the bottom left for the next items
	xOffset.x -= fLeftDialogsWidth;
	xOffset.y += Asura_Dialog::DefaultSpacing();


	//If supporting PS2 then the near fog plane needs to be at least 11 metres , otherwise it should be okay
	//to go lower. RAR 20/06/2007
	const float s_fMinAllowedFogDistance = Tools_Level_Export::IsPlatformSupported(Tools_Level_Export::Export_PS2) ? 11.0f : 0.0f;

	pxDialog = new Asura_Numerical_Dialog( "Near fog plane (m)", xOffset, &s_fFogNearPlane, s_fMinAllowedFogDistance, 2000.0f, 1.0f, "%5.0f", &s_bChangedMinFog );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Far fog plane (m)", xOffset, &s_fFogFarPlane, s_fMinAllowedFogDistance, 10000.0f, 1.0f, "%5.0f", &s_bChangedMaxFog );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	if ( !s_bGraphFogEnabled )
	{
		pxDialog = new Asura_Numerical_Dialog( "Fog value at far plane (%)", xOffset, &s_fFogValueAtFarPlane, fMIN_VALUE_FOR_FOG_AT_FAR_PLANE, 100.0f, 1.0f, "%3.0f", &s_bMadeChanges );
		pxOverlay->AddDialog(pxDialog);
	}
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	//
	// End of 'generic' fog
	//

	// Graph fog. But for the moment it is temporary disabled. I need to do more tests on it. EP.15.Jan.2009

//	pxDialog = new Asura_Tickbox_Dialog("Graph Fog (slightly more costly)", xOffset, &s_bGraphFogEnabled, &s_bChangedFogOverlay);
//	pxDialog->SetHelpText("Graph fog allows you to create a non-linear fog density graph. More complex than regular fog and so marginally slower.");
//	pxOverlay->AddDialog(pxDialog);
//	xOffset.y += Asura_Dialog::DefaultSpacing();

	if ( s_bGraphFogEnabled )
	{
		pxDialog = new Asura_Graph_Dialog<float>("Fog density graph", xOffset, s_pxFogDensityGraph, 0.0f, 1.0f, &s_bMadeChanges);
		pxDialog->SetHelpText("This graph defines the relationship between distance and fog density. The X-Axis represents the distance range between the Near and Far fog planes. The Y-Axis represents fog density.");
		pxOverlay->AddDialog(pxDialog);
		xOffset.y = pxDialog->m_xMaxCoord.y;
	}

	xOffset.y += Asura_Dialog::SmallSpacing();

	//
	// End of 'graph' fog
	//


	pxDialog= new Asura_Function_Dialog( "Okay", xOffset, OkayPressed, reinterpret_cast< int >( this ), &pxOverlay->m_bShouldClose );
	pxOverlay->AddDialog( pxDialog );
	xOffset.x += 7.0f;

	pxDialog= new Asura_Function_Dialog( "Cancel", xOffset, CancelPressed, reinterpret_cast< int >( this ), &pxOverlay->m_bShouldClose );
	pxOverlay->AddDialog( pxDialog );
}

void Tools_EffectVolume_FogOverlay ::Update()
{
	if( s_bChangedFogOverlay )
	{
		s_bChangedFogOverlay = false;
		m_xFogParameters.EnableGraphFog( s_bGraphFogEnabled );
		RebuildOverlay();
	}


	if( s_bMadeChanges )
	{
		// Nasty hacks that I have copied from the Weather system. This is actually how the nasty hacks are spreading trough source code 
		// like cancer. :-)
		if (1)
		{
			// (AW - 20.08.2004) - Nasty hack to stop user from moving the first graph point.
			s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_xValue = 0.0f;
			// Nasty hack to stop user adding new control points.
			if (s_pxFogDensityGraph->GetNumberOfSplinePoints() > 5)
			{
				while (s_pxFogDensityGraph->GetNumberOfSplinePoints() > 4)
				{
					s_pxFogDensityGraph->RemovePoint(s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext);
				}
			}
			// Nasty hack to stop user removing control points.
			if (s_pxFogDensityGraph->GetNumberOfSplinePoints() < 5)
			{
				Asura_Vector_2 xGraphPoint = Asura_Fog::GetGraphFogPoint();
				s_pxFogDensityGraph->AddPoint(xGraphPoint.y, xGraphPoint.x);
			}
			// Nasty hack to stop user setting final fog value too low.
			if (s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_pxNext->m_xValue < fMIN_VALUE_FOR_FOG_AT_FAR_PLANE * 0.01f)
			{	
				s_pxFogDensityGraph->GetControlPoints()->m_pxNext->m_pxNext->m_pxNext->m_xValue = fMIN_VALUE_FOR_FOG_AT_FAR_PLANE * 0.01f;
			}
		}
	}

	
	// Preview current fog 
	Asura_Fog_Parameters xFogParameters;
	WriteNewValuesToFogParameters( xFogParameters );
	Asura_Fog::SetFog( xFogParameters );
	// End of preview current fog.


	//allow escape to be used for cancel
	if(Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_ESCAPE))
	{
		GetOverlay()->m_bShouldClose = true;			
		Tools_System::CancelModeChange();
	}

	PARENT::Update();
}

bool Tools_EffectVolume_FogOverlay ::DoModal()
{
	m_bReturnValue = false;
	ShowOverlay();
	return m_bReturnValue;
}

void Tools_EffectVolume_FogOverlay ::OkayPressed( int iUserData )
{
	Tools_EffectVolume_FogOverlay * pxThis = reinterpret_cast< Tools_EffectVolume_FogOverlay * >( iUserData );
	pxThis->m_bReturnValue = true;
}
void Tools_EffectVolume_FogOverlay ::CancelPressed( int iUserData )
{
	Tools_EffectVolume_FogOverlay * pxThis = reinterpret_cast< Tools_EffectVolume_FogOverlay * >( iUserData );
	pxThis->m_bReturnValue = false;
}



