// ------------------------------------------------------------------------------------ //
//																						//
//	File: Asura_GUIMenu_Widget_ProgressBar.cpp											//
//																						//
//	Description: progressbar widgets class													//
//																						//
//	Created: Steve Keen - 25/01/07														//
//																						//
//	Copyright (C) 2006 Rebellion (Derby), All Rights Reserved.							//
// ------------------------------------------------------------------------------------ //

#include "Core/Asura.h"

#include "GuiMenu/Asura_GUIMenu_Widget_ProgressBar.h"

#ifdef ASURA_USE_GUI_MENU_SYSTEM
#include "Core/Asura_Hash.h"
#include "Core/Asura_String.h"
#include "Core/Memory/Asura_Mem.h"
#include "GUIMenu/Asura_GUIMenu_Element_Base.h"
#include "GUIMenu/Asura_GUIMenu_Element_Image.h"
#include "GUIMenu/Asura_GUIMenu_Element_Path.h"
#include "GUIMenu/Asura_GUIMenu_Message.h"
#include "GUIMenu/Asura_GUIMenu_MessagePump.h"
#include "GUIMenu/Asura_Profiling_GUIMenu.h"
#include "Rendering/Asura_Overlay_Quad.h"
#include "Rendering/Asura_Render.h"
#ifdef ASURA_TOOLS
#include "GUIMenu/Tools_GUIMenu_XMLExporter.h"
#endif

void Asura_GUIMenu_ProgressBar_Overlay_Info::Reset()
{
	m_uHashImageID = ASURA_HASH_ID_UNSET;

	m_xCurrentRect.Set( 0.0f,0.0f,0.0f,0.0f );

	m_xOrgUV.Zero();
	m_xCurrentUV.Zero();
	
	m_eAxisMovement = ASURA_GUIMENU_PROGRESSBAR_AXIS_NONE;

	m_uOverlayFlags = 0;
}

void Asura_GUIMenu_ProgressBar_Overlay_Info::CopyFromElementImage( const Asura_GUIMenu_Element_Image* const pxImage )
{
	if( pxImage )
	{
		m_uHashImageID = pxImage->GetID();
		
		m_xOrgUV.xUV0 = pxImage->GetUV( 0);
		m_xOrgUV.xUV1 = pxImage->GetUV( 1);
	}
}

// --------------------------------------------------------------------------------------- 
// -- Constructors -----------------------------------------------------------------------

Asura_GUIMenu_Widget_ProgressBar::Asura_GUIMenu_Widget_ProgressBar(void)
: m_fElapsedTime( 0.0f)
, m_fPosition( 0.0f)
, m_fOldPosition( 0.0f)
, m_fMinValue( 0.0f)
, m_fMaxValue( 1.0f)
, m_fStepValue( 0.0f)
, m_bUpdatePositionFromConsoleVar(false)
{
	

	m_uType = ASURA_GUIMENU_TYPEID_WIDGET_PROGRESSBAR;

	for( u_int u(0); u<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS; u++)
	{
		m_axImageOverlayToChange[u].Reset();
	}

	ASURA_GUIMENU_PROFILE_COUNTINSTANCE(ASURA_GUIMENU_COUNTER__WIDGET_PROGRESSBAR);
}

// --------------------------------------------------------------------------------------- 
// -- Destructor -------------------------------------------------------------------------

Asura_GUIMenu_Widget_ProgressBar::~Asura_GUIMenu_Widget_ProgressBar(void)
{
	ASURA_GUIMENU_PROFILE_COUNTDESTROYINSTANCE(ASURA_GUIMENU_COUNTER__WIDGET_PROGRESSBAR);
}

// --------------------------------------------------------------------------------------- 
// -- Public Functions ------------------------------------------------------------------- 

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::Render( u_int uState)
{
	ASURA_GUIMENU_PROFILE_START_TASK(ASURA_GUIMENU_PROFILE__WIDGET_PROGRESSBAR);

	int iOverlayIndex;
	Asura_GUIMenu_Widget_State eState;

	if( !IsRenderingDisabled() )
	{
		float fConditionVal = ConvertToRange( m_fPosition);

		eState = GetCurrentState();

		const u_int uContainerCount = GetContainerCount();
		for( u_int u=0; u<uContainerCount; u++)
		{
			if( m_ppxContainerParts[u]->IsActionEnabled( eState))
			{
				if( m_ppxContainerParts[u]->IsDisplayConditionMet( (int)fConditionVal) == true)
				{
					iOverlayIndex = IsImageOverlay( m_ppxContainerParts[u]->GetID());

					if( iOverlayIndex != -1)
					{
						RenderImageOverlay( iOverlayIndex, u);
					}
					else
					{
						m_ppxContainerParts[u]->Render( uState);
					}
				}
			}
		}
	}

	ASURA_GUIMENU_PROFILE_END_TASK();
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::RenderImageOverlay( u_int uOverlayIndex, u_int uContainerIndex)
{
	if(uOverlayIndex < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS)
	{
		const Asura_GUIMenu_Element_Image* pxImage = static_cast<Asura_GUIMenu_Element_Image*>(m_ppxContainerParts[uContainerIndex]);
		if( pxImage != NULL)
		{
			Asura_GUIMenu_ProgressBar_Overlay_Info* pxOverlay = GetActiveOverlayImageDataPtr( uOverlayIndex);

			UpdateProgressBarElementInfo(pxOverlay, pxImage);

			Asura_Render::Overlay.Colour = pxImage->GetColour().ToUIntARGB();
			Asura_Render::Overlay.m_bNonRotated = true;
			Asura_Render::Overlay.m_bGouraudShaded = false;
			Asura_Render::Overlay.TextureIndex = pxImage->GetTexture();
			Asura_Render::Overlay.TranslucencyMode = pxImage->GetTranslucencyMode();
			Asura_Render::Overlay.SetRectXY( pxOverlay->m_xCurrentRect.MinX,
							pxOverlay->m_xCurrentRect.MinY,
							pxOverlay->m_xCurrentRect.GetWidth(),
							pxOverlay->m_xCurrentRect.GetHeight());

			// -- top-left
			Asura_Render::Overlay.U[0] = pxOverlay->m_xCurrentUV.xUV0.u;
			Asura_Render::Overlay.V[0] = pxOverlay->m_xCurrentUV.xUV0.v;

			// -- top-right
			Asura_Render::Overlay.U[1] = pxOverlay->m_xCurrentUV.xUV1.u;
			Asura_Render::Overlay.V[1] = pxOverlay->m_xCurrentUV.xUV0.v;

			// -- bottom-right
			Asura_Render::Overlay.U[2] = pxOverlay->m_xCurrentUV.xUV1.u;
			Asura_Render::Overlay.V[2] = pxOverlay->m_xCurrentUV.xUV1.v;

			// -- bottom-left
			Asura_Render::Overlay.U[3] = pxOverlay->m_xCurrentUV.xUV0.u;
			Asura_Render::Overlay.V[3] = pxOverlay->m_xCurrentUV.xUV1.v;

			Asura_Render::Overlay.Render();			

		}
	}
}
// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::Update( float fElapsedTime)	//, unsigned int uButtons, POINT ptMousePos)
{
	ASURA_GUIMENU_PROFILE_START_TASK(ASURA_GUIMENU_PROFILE__WIDGET_PROGRESSBAR);

	Asura_GUIMenu_Root::Update( fElapsedTime);

	m_fElapsedTime = fElapsedTime;

	switch( GetCurrentState())
	{
		case ASURA_GUIMENU_WIDGET_STATE_DEFAULT:
			break;

		case ASURA_GUIMENU_WIDGET_STATE_ROLL_ON:
			SetCurrentState( ASURA_GUIMENU_WIDGET_STATE_HILIGHTED);
			break;

		case ASURA_GUIMENU_WIDGET_STATE_HILIGHTED:
			break;

		case ASURA_GUIMENU_WIDGET_STATE_CLICKED:
			SetCurrentState( ASURA_GUIMENU_WIDGET_STATE_HILIGHTED);
			break;

		case ASURA_GUIMENU_WIDGET_STATE_ROLL_OFF:
			SetCurrentState( ASURA_GUIMENU_WIDGET_STATE_DEFAULT);
			break;

		case ASURA_GUIMENU_WIDGET_STATE_EDITING:
			break;

		case ASURA_GUIMENU_WIDGET_STATE_DISABLED:
		default:
			break;
	}

	const u_int uContainerCount = GetContainerCount();
	for( u_int u=0; u<uContainerCount; u++)
	{
		m_ppxContainerParts[u]->Update( fElapsedTime);
	}

	UpdatePositionFromConsoleVar();

	ASURA_GUIMENU_PROFILE_END_TASK();
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::Copy( const Asura_GUIMenu_Root* pxSource)
{
	PARENT::Copy( pxSource);

	const Asura_GUIMenu_Widget_ProgressBar* pxSourceProgressBar = static_cast<const Asura_GUIMenu_Widget_ProgressBar*> (pxSource);

	SetMinAndMaxValue( pxSourceProgressBar->m_fMinValue, pxSourceProgressBar->m_fMaxValue);
	SetStepValue( pxSourceProgressBar->m_fStepValue);

	m_xConsoleVar.Copy(&pxSourceProgressBar->m_xConsoleVar);

	m_bUpdatePositionFromConsoleVar = pxSourceProgressBar->m_bUpdatePositionFromConsoleVar;

	CopyOverlayInfo( pxSourceProgressBar);
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::CopyOverlayInfo( const Asura_GUIMenu_Widget_ProgressBar* pxSourceProgressBar)
{
	if( pxSourceProgressBar )
	{
		const Asura_GUIMenu_ProgressBar_Overlay_Info* pxOverlayInfo = NULL;
		Asura_GUIMenu_Root* pxSourceItem = NULL;
		Asura_GUIMenu_Root* pxDestItem = NULL;

		Asura_String xLocalName;

		for( u_int u(0); u<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS; u++)
		{
			pxOverlayInfo  = &pxSourceProgressBar->m_axImageOverlayToChange[u];
			if( pxOverlayInfo != NULL)
			{
				pxSourceItem = pxSourceProgressBar->SearchForOverlayContainerItem( pxOverlayInfo->m_uHashImageID);
				if( pxSourceItem)
				{
					pxDestItem = FindContainerItemByLocalNameHash( pxSourceItem->GetNameHash());

					if( pxDestItem)
					{
						SetActiveOverlayImageData( u, pxDestItem->GetID(),
												   pxOverlayInfo->m_eAxisMovement,
												   pxOverlayInfo->m_uOverlayFlags);

					}
				}
			}
		}

		// copy console var
		m_xConsoleVar = pxSourceProgressBar->GetConsoleVar();
		m_bUpdatePositionFromConsoleVar = !m_xConsoleVar.IsBlank();
	}

}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::Resize( const Asura_Bounding_Rectangle& xBounds )
{
	PARENT::Resize(xBounds);

	UpdateActiveOverlayImageData();
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::UpdateProgressBarElementInfo(Asura_GUIMenu_ProgressBar_Overlay_Info* pxOverlay, const Asura_GUIMenu_Element_Image* pxImage)
{
	if(pxImage && pxOverlay)
	{
		pxOverlay->m_xCurrentRect = pxImage->GetScaledWorldBounds();
		pxOverlay->m_xOrgUV.xUV0 = pxImage->GetUV(0);
		pxOverlay->m_xOrgUV.xUV1 = pxImage->GetUV(1);
		pxOverlay->m_xCurrentUV   = pxOverlay->m_xOrgUV;

		switch( pxOverlay->m_eAxisMovement)
		{
			case ASURA_GUIMENU_PROGRESSBAR_AXIS_NORTH:
			{
				float fHeight = pxOverlay->m_xCurrentRect.MaxY - pxOverlay->m_xCurrentRect.MinY;
				pxOverlay->m_xCurrentRect.MinY = pxOverlay->m_xCurrentRect.MaxY - (fHeight * m_fPosition);

				if ((pxOverlay->m_uOverlayFlags & ASURA_GUIMENU_PROGRESSBAR_FLAGS_CLIP_OVERLAY) != 0)
				{
					float fUVHeight = pxOverlay->m_xOrgUV.xUV1.v - pxOverlay->m_xOrgUV.xUV0.v;
					pxOverlay->m_xCurrentUV.xUV0.v = pxOverlay->m_xOrgUV.xUV1.v - (fUVHeight * m_fPosition);
				}

				break;
			}

			case ASURA_GUIMENU_PROGRESSBAR_AXIS_EAST:
			{
				float fWidth = pxOverlay->m_xCurrentRect.MaxX - pxOverlay->m_xCurrentRect.MinX;
				pxOverlay->m_xCurrentRect.MaxX = pxOverlay->m_xCurrentRect.MinX + fWidth * m_fPosition;

				if ( (pxOverlay->m_uOverlayFlags & ASURA_GUIMENU_PROGRESSBAR_FLAGS_CLIP_OVERLAY) != 0)
				{	
					float fUVWidth = pxOverlay->m_xOrgUV.xUV1.u - pxOverlay->m_xOrgUV.xUV0.u;
					pxOverlay->m_xCurrentUV.xUV1.u = pxOverlay->m_xOrgUV.xUV0.u + (fUVWidth * m_fPosition);
				}
				break;
			}

			case ASURA_GUIMENU_PROGRESSBAR_AXIS_SOUTH:
			{
				float fHeight = pxOverlay->m_xCurrentRect.MaxY - pxOverlay->m_xCurrentRect.MinY;
				pxOverlay->m_xCurrentRect.MaxY = pxOverlay->m_xCurrentRect.MinY + fHeight * m_fPosition;

				if ((pxOverlay->m_uOverlayFlags & ASURA_GUIMENU_PROGRESSBAR_FLAGS_CLIP_OVERLAY) != 0)
				{	
					float fUVHeight = pxOverlay->m_xOrgUV.xUV1.v - pxOverlay->m_xOrgUV.xUV0.v;
					pxOverlay->m_xCurrentUV.xUV1.v = pxOverlay->m_xOrgUV.xUV0.v + (fUVHeight * m_fPosition);
				}

				break;
			}

			case ASURA_GUIMENU_PROGRESSBAR_AXIS_WEST:
			{
				float fWidth = pxOverlay->m_xCurrentRect.MaxX - pxOverlay->m_xCurrentRect.MinX;
				pxOverlay->m_xCurrentRect.MinX = pxOverlay->m_xCurrentRect.MaxX - (fWidth * m_fPosition);

				if( (pxOverlay->m_uOverlayFlags & ASURA_GUIMENU_PROGRESSBAR_FLAGS_CLIP_OVERLAY) != 0)
				{	
					float fUVWidth = pxOverlay->m_xOrgUV.xUV1.u - pxOverlay->m_xOrgUV.xUV0.u;
					pxOverlay->m_xCurrentUV.xUV0.u = pxOverlay->m_xOrgUV.xUV1.u - (fUVWidth * m_fPosition);
				}
				break;
			}

			default:
			{
				break;
			}
		}
	}
}

void Asura_GUIMenu_Widget_ProgressBar::UpdatePositionFromConsoleVar()
{
	if( m_bUpdatePositionFromConsoleVar )
	{	
		float fConsoleVarValue(0.0f);
		const Asura_CommandConsole_VarRepository::Var::TYPE eType( m_xConsoleVar.GetType() );

		if( eType == Asura_CommandConsole_VarRepository::Var::TYPE_INVALID )
		{
			// update() should try to discover the var type from the command console
			m_xConsoleVar.Update();
		}
		else if( eType == Asura_CommandConsole_VarRepository::Var::TYPE_FLOAT )
		{	
			m_xConsoleVar.GetFloatValue( fConsoleVarValue );
		}
		else if( eType == Asura_CommandConsole_VarRepository::Var::TYPE_INT )
		{
			int iConsoleVarValue(0);
			m_xConsoleVar.GetIntValue( iConsoleVarValue );
			fConsoleVarValue = static_cast<float>(iConsoleVarValue);
		}

		UpdateBarPos( fConsoleVarValue );
	}
}

// --------------------------------------------------------------------------------------- 
// -- UI Message handler functions -------------------------------------------------------

bool Asura_GUIMenu_Widget_ProgressBar::OnInit( const Asura_Message_GUIMenu_Notify* pxMessage)
{
	PARENT::OnInit( pxMessage);

	Asura_GUIMenu_MessagePump::PostMessage( ASURA_GUIMENU_EXTERNAL_REQUEST, GetID(), ASURA_GUIMENU_UI_MSG_ON_DATA_REQUEST, ASURA_GUIMENU_TYPEID_WIDGET_PROGRESSBAR);		
	return true;
}

// --------------------------------------------------------------------------------------- 

bool Asura_GUIMenu_Widget_ProgressBar::OnDeInit( const Asura_Message_GUIMenu_Notify* pxMessage)
{
	if( GetFlag( ASURA_GUIMENU_ACTION_FLAG_NOTIFY_DATA_CHANGE_IMMEDIATE) == true)
	{
		Asura_GUIMenu_MessagePump::PostMessage( ASURA_GUIMENU_EXTERNAL_NOTIFY, GetID(), ASURA_GUIMENU_UI_MSG_ON_DATA_CHANGE, ASURA_GUIMENU_TYPEID_WIDGET_PROGRESSBAR, (u_int)Asura_Maths::FloatToInt( m_fPosition * 100.0f));
	}

	return true;
}

// --------------------------------------------------------------------------------------- 

bool Asura_GUIMenu_Widget_ProgressBar::OnDataChange( const Asura_Message_GUIMenu_Notify* pxMessage)
{
	bool bHandled = false;
	float fFinalValue;

	if( pxMessage->uFromID != GetID())
	{
		// -- something external has changed the data --
		if( pxMessage->WidgetType == ASURA_GUIMENU_TYPEID_WIDGET_PROGRESSBAR)
		{
			switch( ASURA_GUIMENU_GET_SUB_MESSAGE( pxMessage->uActionType))
			{
				case ASURA_GUIMENU_PROGRESSBAR_SETPOSITION:
				{
					UpdateBarPos( (float)pxMessage->uData/100.0f);
				}
				break;

				case ASURA_GUIMENU_PROGRESSBAR_GETPOSITION:
				{
					fFinalValue = ConvertToRange( m_fPosition);

					// -- something external has requested the data --
					// -- the final value is always multiplied because it could be a fractional value --
					Asura_GUIMenu_MessagePump::PostMessage( pxMessage->uFromID, GetID(), ASURA_GUIMENU_UI_MSG_ON_DATA_CHANGE, ASURA_GUIMENU_TYPEID_WIDGET_PROGRESSBAR, (u_int)Asura_Maths::FloatToInt( fFinalValue * 100.0f));
				}
				break;

				case ASURA_GUIMENU_PROGRESSBAR_ADD_STEP:
				{
					AddStep();
				}
				break;

				case ASURA_GUIMENU_PROGRESSBAR_SUBTRACT_STEP:
				{
					SubstractStep();
				}
				break;

			}
		}

		bHandled = true;
	}
	return bHandled;
}

// --------------------------------------------------------------------------------------- 

bool Asura_GUIMenu_Widget_ProgressBar::OnDataRequest( const Asura_Message_GUIMenu_Notify* pxMessage)
{
	bool bHandled = false;
	float fRange, fFinalValue;
	float fMin, fMax;

	if( pxMessage->uFromID != GetID())
	{
		fMin = GetMinimumValue();
		fMax = GetMaximumValue();

		fRange = fMax - fMin;
		fFinalValue = fMin + (fRange * m_fPosition);

		// -- something external has requested the data --
		// -- the final value is always multiplied because it could be a fractional value --
		Asura_GUIMenu_MessagePump::PostMessage( pxMessage->uFromID, GetID(), ASURA_GUIMENU_UI_MSG_ON_DATA_CHANGE, ASURA_GUIMENU_TYPEID_WIDGET_PROGRESSBAR, (u_int)Asura_Maths::FloatToInt( fFinalValue * 100.0f));
		bHandled = true;
	}
	return bHandled;

}

// --------------------------------------------------------------------------------------- 

bool Asura_GUIMenu_Widget_ProgressBar::OnClicked( const Asura_Message_GUIMenu_Notify* pxMessage)
{
	return true;
}

// --------------------------------------------------------------------------------------- 

bool Asura_GUIMenu_Widget_ProgressBar::OnRollIn( const Asura_Message_GUIMenu_Notify* pxMessage)
{
	SetCurrentState( ASURA_GUIMENU_WIDGET_STATE_ROLL_ON);
	return true;
}

// --------------------------------------------------------------------------------------- 

bool Asura_GUIMenu_Widget_ProgressBar::OnRollOut( const Asura_Message_GUIMenu_Notify* pxMessage)
{
	SetCurrentState( ASURA_GUIMENU_WIDGET_STATE_ROLL_OFF);
	return true;
}

// --------------------------------------------------------------------------------------- 

bool Asura_GUIMenu_Widget_ProgressBar::OnEnable( const Asura_Message_GUIMenu_Notify* pxMessage)
{
Asura_GUIMenu_Widget_State eNewState;

	if( pxMessage->uData != 0)
	{	
		if( IsFocusedObject())
		{	eNewState = ASURA_GUIMENU_WIDGET_STATE_HILIGHTED;	}
		else
		{	eNewState = ASURA_GUIMENU_WIDGET_STATE_DEFAULT;	}
	}
	else
	{
		eNewState = ASURA_GUIMENU_WIDGET_STATE_DISABLED;	
	}

	SetCurrentState( eNewState);

	return true;
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::SetActiveOverlayImageData( const u_int uIndex,
																  const Asura_Hash_ID uHashImageID,
																  const Asura_GUIMenu_ProgressBar_Axis_Movement eAxisMovement,
																  const u_int uOverlayFlags /* = 0 */)
{
	Asura_GUIMenu_Root* pxItem = NULL;
	Asura_GUIMenu_Element_Image* pxImageItem = NULL;

	Asura_Assert( uIndex < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS, "Asura_GUIMenu_Widget_ProgressBar::SetActiveOverlayImage - uIndex >= MAX_PROGRESSBAR_IMAGE_OVERLAYS");

	if( uIndex < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS)
	{
		pxItem = FindContainerItemByID( uHashImageID);

		if( pxItem && ( pxItem->GetType() == ASURA_GUIMENU_TYPEID_ELEMENT_IMAGE) )
		{
			pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(pxItem);

			m_axImageOverlayToChange[uIndex].CopyFromElementImage( pxImageItem );
			m_axImageOverlayToChange[uIndex].m_eAxisMovement = eAxisMovement;
			m_axImageOverlayToChange[uIndex].m_uOverlayFlags = uOverlayFlags;	
		}
		else
		{
			m_axImageOverlayToChange[uIndex].Reset();
		}
	}
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::UpdateActiveOverlayImageData()
{
	for( u_int u(0);u<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS;++u )
	{
		if( m_axImageOverlayToChange[u].m_uHashImageID != ASURA_HASH_ID_UNSET )
		{
			Asura_GUIMenu_Root* pxRoot( FindContainerItemByID( m_axImageOverlayToChange[u].m_uHashImageID));

			Asura_Assert( pxRoot,"Failed to find GUI item associated with progress bar overlay" );

			if( pxRoot && ( pxRoot->GetType() == ASURA_GUIMENU_TYPEID_ELEMENT_IMAGE) )
			{
				m_axImageOverlayToChange[u].CopyFromElementImage(  static_cast<Asura_GUIMenu_Element_Image*>(pxRoot) );
			}
		}
	}
}

// --------------------------------------------------------------------------------------- 

Asura_GUIMenu_ProgressBar_Overlay_Info Asura_GUIMenu_Widget_ProgressBar::GetActiveOverlayImageData( u_int uIndex) const
{
	Asura_GUIMenu_ProgressBar_Overlay_Info xInfo;

	Asura_Mem::Set( &xInfo, 0, sizeof(Asura_GUIMenu_ProgressBar_Overlay_Info));

	Asura_Assert( uIndex < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS, "Asura_GUIMenu_Widget_ProgressBar::SetActiveOverlayImage - uIndex >= MAX_PROGRESSBAR_IMAGE_OVERLAYS");

	if( uIndex < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS)
	{
		xInfo = m_axImageOverlayToChange[uIndex];
	}

	return xInfo;
}

// --------------------------------------------------------------------------------------- 

Asura_GUIMenu_ProgressBar_Overlay_Info* Asura_GUIMenu_Widget_ProgressBar::GetActiveOverlayImageDataPtr( u_int uIndex)
{
	Asura_GUIMenu_ProgressBar_Overlay_Info* pxInfo = NULL;

	Asura_Assert( uIndex < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS, "Asura_GUIMenu_Widget_ProgressBar::SetActiveOverlayImage - uIndex >= MAX_PROGRESSBAR_IMAGE_OVERLAYS");

	if( uIndex < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS)
	{
		pxInfo = &m_axImageOverlayToChange[uIndex];
	}

	return pxInfo;
}

// --------------------------------------------------------------------------------------- 

int Asura_GUIMenu_Widget_ProgressBar::IsImageOverlay( Asura_Hash_ID uHashID)
{
	for (int i = 0; i < ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS; ++i)
	{
		if( m_axImageOverlayToChange[i].m_uHashImageID == uHashID)
		{
			return i;
		}
	}

	return -1;
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::SetMaximumValue( float fMax)
{
	Asura_Assert( fMax > GetMinimumValue(), "Asura_GUIMenu_Widget_ProgressBar::SetMaximumValue - Max value specified is less than the minimum value.  This value will not be set.");

	if( fMax > GetMinimumValue())
	{
		m_fMaxValue = fMax;
	}
}

// --------------------------------------------------------------------------------------- 

float Asura_GUIMenu_Widget_ProgressBar::GetMaximumValue( void) const
{ 
	return m_fMaxValue;
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::SetMinimumValue( float fMin)
{
	Asura_Assert( fMin < GetMaximumValue(), "Asura_GUIMenu_Widget_ProgressBar::SetMinimumValue - Min value specified is greater than the maximum value.  This value will not be set.");

	if( fMin < GetMaximumValue())
	{
		m_fMinValue = fMin;
	}
}

// --------------------------------------------------------------------------------------- 

float Asura_GUIMenu_Widget_ProgressBar::GetMinimumValue( void) const
{
	return m_fMinValue;
}

// --------------------------------------------------------------------------------------- 
void Asura_GUIMenu_Widget_ProgressBar::SetMinAndMaxValue(float fMin, float fMax)
{
	Asura_Assert(fMin<=fMax,"Asura_GUIMenu_Widget_ProgressBar::SetMinAndMaxValue - minimum should be less than maximum");
	m_fMinValue = Asura_Maths::Min(fMin,fMax);
	m_fMaxValue = Asura_Maths::Max(fMin,fMax);

}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::SetStepValue( float fStep)
{
	float fRange = GetMaximumValue() - GetMinimumValue();

	Asura_Assert( fStep <= fRange, "Asura_GUIMenu_Widget_ProgressBar::SetStepValue - Step specified is greater than the range given by Min & Max.");

	if( fStep <= fRange)
	{
		m_fStepValue = fStep;
	}
}
// --------------------------------------------------------------------------------------- 

float Asura_GUIMenu_Widget_ProgressBar::GetStepValue( void) const
{
	return m_fStepValue;
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::AddStep( void)
{
	UpdateBarPos( ConvertToRange( m_fPosition) + GetStepValue());
}

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::SubstractStep( void)
{
	UpdateBarPos( ConvertToRange( m_fPosition) - GetStepValue());
}

// --------------------------------------------------------------------------------------- 

// --------------------------------------------------------------------------------------- 
// -- Protected Functions ------------------------------------------------------------------

void Asura_GUIMenu_Widget_ProgressBar::UpdateBarPos( float fNewPos)
{
	
	// if less than min set position to 0
	if( fNewPos < GetMinimumValue() )
	{
		m_fPosition = 0.0f;
	}
	// if greater than max set position to 1
	else if( fNewPos > GetMaximumValue() )
	{
		m_fPosition = 1.0f;
	}
	// value is in range
	else
	{
		m_fPosition = ConvertFromRange( fNewPos);

		if( m_fPosition > 1.0f)
		{	m_fPosition = 1.0f;	}

		if( m_fPosition < 0.0f)
		{	m_fPosition = 0.0f;	}
	}
}
// --------------------------------------------------------------------------------------- 

float Asura_GUIMenu_Widget_ProgressBar::ConvertToRange( float fNewPos)
{
	float fRange, fCurrentPos;
	float fMin, fMax;

	fMin = GetMinimumValue();
	fMax = GetMaximumValue();

	fRange = fMax - fMin;
	fCurrentPos = fMin + (fRange * m_fPosition);

	return fCurrentPos;
}

// --------------------------------------------------------------------------------------- 

float Asura_GUIMenu_Widget_ProgressBar::ConvertFromRange( float fNewPos)
{
	float fPos;

	fPos = fNewPos - GetMinimumValue();

	fPos /= (GetMaximumValue() - GetMinimumValue());

	return fPos;
}

// --------------------------------------------------------------------------------------- 

Asura_GUIMenu_Root* Asura_GUIMenu_Widget_ProgressBar::SearchForOverlayContainerItem( Asura_Hash_ID uSearchID) const
{
	u_int i;
	Asura_GUIMenu_Root* pxItem = NULL;
	Asura_GUIMenu_Root* pxFoundItem = NULL;

	for( i=0; i<GetContainerCount(); i++)
	{
		pxItem = GetContainerItem( i);
		if( pxItem->GetID() == uSearchID)
		{
			pxFoundItem = pxItem;
			break;
		}
	}

	return pxFoundItem;
}

// --------------------------------------------------------------------------------------- 

#ifdef ASURA_TOOLS
void Asura_GUIMenu_Widget_ProgressBar::UpdateLocalDataFromStyle( void)
{
	Asura_GUIMenu_Widget_ProgressBar* pxStyleBar;

	PARENT::UpdateLocalDataFromStyle();

	if( m_pxStyleObject != NULL)
	{
		if( (m_uStyleUseLocalDataFlags&ASURA_GUIMENU_WIDGET_PROGRESSBAR_LOCAL_FLAG_MINIMUM) == 0)
		{
			pxStyleBar = static_cast<Asura_GUIMenu_Widget_ProgressBar*>(m_pxStyleObject);
			SetMinimumValue( pxStyleBar->GetMinimumValue());
		}

		if( (m_uStyleUseLocalDataFlags&ASURA_GUIMENU_WIDGET_PROGRESSBAR_LOCAL_FLAG_MAXIMUM) == 0)
		{
			pxStyleBar = static_cast<Asura_GUIMenu_Widget_ProgressBar*>(m_pxStyleObject);
			SetMaximumValue( pxStyleBar->GetMaximumValue());
		}

		if( (m_uStyleUseLocalDataFlags&ASURA_GUIMENU_WIDGET_PROGRESSBAR_LOCAL_FLAG_STEP) == 0)
		{
			pxStyleBar = static_cast<Asura_GUIMenu_Widget_ProgressBar*>(m_pxStyleObject);
			SetStepValue( pxStyleBar->GetStepValue());
		}

		if( (m_uStyleUseLocalDataFlags&ASURA_GUIMENU_WIDGET_PROGRESSBAR_LOCAL_FLAG_OVERLAYS) == 0)
		{
			pxStyleBar = static_cast<Asura_GUIMenu_Widget_ProgressBar*>(m_pxStyleObject);
			CopyOverlayInfo( pxStyleBar);			
		}

	}
}
#endif

// --------------------------------------------------------------------------------------- 

void Asura_GUIMenu_Widget_ProgressBar::ApplyScalingFlagsToChildren()
{
	PARENT::ApplyScalingFlagsToChildren();
	
	for( u_int u(0);u<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS;++u )
	{
		if( m_axImageOverlayToChange[u].m_uHashImageID != ASURA_HASH_ID_UNSET )
		{
			Asura_GUIMenu_Root* pxRoot( FindContainerItemByID( m_axImageOverlayToChange[u].m_uHashImageID));

			Asura_Assert( pxRoot,"Failed to find GUI item associated with progress bar overlay" );

			if( pxRoot )
			{
				pxRoot->SetScalingFlags( GetScalingFlags() );
			}
		}
	}
}

void Asura_GUIMenu_Widget_ProgressBar::ApplyAnchoringFlagsToChildren()
{
	PARENT::ApplyAnchoringFlagsToChildren();

	for( u_int u(0);u<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS;++u )
	{
		if( m_axImageOverlayToChange[u].m_uHashImageID != ASURA_HASH_ID_UNSET )
		{
			Asura_GUIMenu_Root* pxRoot( FindContainerItemByID( m_axImageOverlayToChange[u].m_uHashImageID));

			Asura_Assert( pxRoot,"Failed to find GUI item associated with progress bar overlay" );

			if( pxRoot )
			{
				pxRoot->SetPosMode( 0,GetPosMode(0) );
				pxRoot->SetPosMode( 1,GetPosMode(1) );
			}
		}
	}
}

#ifdef ASURA_TOOLS
const bool Asura_GUIMenu_Widget_ProgressBar::FindAndReplaceConsoleVarName( const Asura_UnicodeChar* wszName,const Asura_UnicodeChar* wszReplacementName )
{
	bool bRtn(false);
	
	bRtn |= PARENT::FindAndReplaceConsoleVarName( wszName,wszReplacementName );
	bRtn |= m_xConsoleVar.FindAndReplaceConsoleVarName( wszName,wszReplacementName );

	return bRtn;
}
#endif // ASURA_TOOLS

void Asura_GUIMenu_Widget_ProgressBar::ReadFromChunkStream( Asura_Chunk_Stream& xStream, Asura_GUIMenu_Root* pxParentObject, u_int uChunkVersion)
{
	u_int u, uHashImageID, uAxisMovement, uOverlayFlags;

	PARENT::ReadFromChunkStream( xStream, pxParentObject, 0xffffffff);

	ReadAllChildObjects( xStream, this);

	// read in progressbar specific data --
	float fTemp;

	xStream >> fTemp;
	SetMaximumValue( fTemp);

	xStream >> fTemp;
	SetMinimumValue( fTemp);

	xStream >> fTemp;				
	SetStepValue( fTemp);

	if( uChunkVersion > 0 )
	{
		m_xConsoleVar.ReadFromChunkStream( xStream );
		m_bUpdatePositionFromConsoleVar = !m_xConsoleVar.IsBlank();
	}

	// -- read in the adjustable overlay info --
	for( u=0; u<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS; ++u )
	{
		xStream >> uHashImageID;				
		xStream >> uAxisMovement;
		xStream >> uOverlayFlags;

		SetActiveOverlayImageData( u, uHashImageID, (Asura_GUIMenu_ProgressBar_Axis_Movement)uAxisMovement, uOverlayFlags);
	}

}

// --------------------------------------------------------------------------------------- 

#ifdef ASURA_TOOLS
void Asura_GUIMenu_Widget_ProgressBar::WriteToChunkStream( Asura_Chunk_Stream& xStream) const
{
	Asura_GUIMenu_ProgressBar_Overlay_Info xInfo;
	u_int i, uAxisMovement;

	WriteLocalChunkHeader( xStream, ASURA_CHUNK_WIDGET_PROGRESSBAR_VERSION, GetType());

	PARENT::WriteToChunkStream( xStream);

	// -- write out any children --
	WriteChildObjectData( xStream);

	// -- write out progressbar data --
	xStream << m_fMaxValue;
	xStream << m_fMinValue;
	xStream << m_fStepValue;

	m_xConsoleVar.WriteToChunkStream( xStream );

	for( i=0; i<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS; ++i )
	{
		xStream << m_axImageOverlayToChange[i].m_uHashImageID;

		uAxisMovement = m_axImageOverlayToChange[i].m_eAxisMovement;
		xStream << uAxisMovement;

		xStream << m_axImageOverlayToChange[i].m_uOverlayFlags;
	}
}

void Asura_GUIMenu_Widget_ProgressBar::ExportToXML(Tools_GUIMenu_XMLExporter* pxExporter) const
{
	PARENT::ExportToXML( pxExporter );

	pxExporter->AddToBuffer( pxExporter->GetTabs() );
	pxExporter->AddToBuffer( "<ProgressBar_data>\n" );
	pxExporter->IncTabs();

	// -- write out progressbar data --
	pxExporter->AddToBuffer( pxExporter->GetTabs() );
	pxExporter->AddToBuffer( "<max_value>" );
	pxExporter->AddToBuffer( m_fMaxValue );
	pxExporter->AddToBuffer( "</max_value>\n" );

	pxExporter->AddToBuffer( pxExporter->GetTabs() );
	pxExporter->AddToBuffer( "<min_value>" );
	pxExporter->AddToBuffer( m_fMaxValue );
	pxExporter->AddToBuffer( "</min_value>\n" );

	pxExporter->AddToBuffer( pxExporter->GetTabs() );
	pxExporter->AddToBuffer( "<step_value>" );
	pxExporter->AddToBuffer( m_fStepValue );
	pxExporter->AddToBuffer( "</step_value>\n" );

	m_xConsoleVar.ExportToXML( pxExporter );

	for(int i=0; i<ASURA_GUIMENU_MAX_PROGRESSBAR_IMAGE_OVERLAYS; ++i)
	{
		pxExporter->AddToBuffer( pxExporter->GetTabs() );
		pxExporter->AddToBuffer( "<progressbar_image_overlay num='" ); pxExporter->AddToBuffer( i ); pxExporter->AddToBuffer( "' >\n" );
		pxExporter->IncTabs();

		pxExporter->AddToBuffer( pxExporter->GetTabs() ); pxExporter->AddToBuffer( "<image_id>" );
		pxExporter->AddToBufferHex( m_axImageOverlayToChange[i].m_uHashImageID ); pxExporter->AddToBuffer( "</image_id>\n" );

		pxExporter->AddToBuffer( pxExporter->GetTabs() ); pxExporter->AddToBuffer( "<axis_movement>" );
		pxExporter->AddToBuffer( m_axImageOverlayToChange[i].m_eAxisMovement ); pxExporter->AddToBuffer( "</axis_movement>\n" );
		
		pxExporter->AddToBuffer( pxExporter->GetTabs() ); pxExporter->AddToBuffer( "<overlay_flags>" );
		pxExporter->AddToBuffer( m_axImageOverlayToChange[i].m_uOverlayFlags ); pxExporter->AddToBuffer( "</overlay_flags>\n" );
		
		pxExporter->DecTabs();
		pxExporter->AddToBuffer( pxExporter->GetTabs() );
		pxExporter->AddToBuffer( "</progressbar_image_overlay>\n" );
	}

	pxExporter->DecTabs();
	pxExporter->AddToBuffer( pxExporter->GetTabs() );
	pxExporter->AddToBuffer( "</ProgressBar_data>\n" );
	
}

#endif // ASURA_TOOLS

// --------------------------------------------------------------------------------------- 
// -- Private Functions ------------------------------------------------------------------


// --------------------------------------------------------------------------------------- 

#endif // ASURA_USE_GUI_MENU_SYSTEM
