#include "hud.h"
#include "room.h"
#include "Mix/Dynamics/IRigidBody.h"

HUD::HUD( void )
{
}

HUD::~HUD( void )
{
}

void HUD::Initialize( Room* pRoom, const Mix::Point& screenSize )
{
	MIX_ASSERT( pRoom != NULL );

	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_pRoom = pRoom;

	////////////////////////////////////////////////////////////////////////////////////////////////////

	SetHUDEnabled( True );
	SetPosition( Mix::Point( screenSize.x - HUD::DLG_WIDTH, screenSize.y - HUD::DLG_HEIGHT ) );
	SetSize( Mix::Point( HUD::DLG_WIDTH, HUD::DLG_HEIGHT ) );

	////////////////////////////////////////////////////////////////////////////////////////////////////

	Int32 itemY = 16;

	m_ListCB.Initialize( this, HUD::CTRL_LIST_CB );
	m_ListCB.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_ListCB.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_ListCB.AddItem( HUD::BUILDING_BILLIARDS, L"Billiards" );
	m_ListCB.AddItem( HUD::BUILDING_PYRAMID, L"Pyramid" );
	m_ListCB.AddItem( HUD::BUILDING_BABEL, L"Babel" );
	m_ListCB.SetSelectedItem( HUD::BUILDING_BILLIARDS, False );
	itemY += HUD::ITEM_Y_STEP;

	m_ExplosionB.Initialize( this, HUD::CTRL_EXPLOSION_B );
	m_ExplosionB.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_ExplosionB.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_ExplosionB.SetText( L"Explosion" );
	itemY += HUD::ITEM_YY_STEP;

	m_ResetB.Initialize( this, HUD::CTRL_RESET_B );
	m_ResetB.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_ResetB.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_ResetB.SetText( L"Reset" );
	itemY += HUD::ITEM_Y_STEP;
}

void HUD::OnDispose( void )
{
}

void HUD::OnButton_Click( Utility::UI::Button* pButton )
{
	switch( pButton->GetID() )
	{
	case HUD::CTRL_EXPLOSION_B:
		if( m_pRoom != NULL )
		{
			switch( m_ListCB.GetSelectedItem() )
			{
			case HUD::BUILDING_BILLIARDS:
				m_pRoom->Explosion( Mix::Vector3( 0.0f, -5.0f, 0.0f ), 30.0f );
				break;
			case HUD::BUILDING_PYRAMID:
				m_pRoom->Explosion( Mix::Vector3( 0.0f, 2.5f, 0.0f ), 15.0f );
				break;
			case HUD::BUILDING_BABEL:
				m_pRoom->Explosion( Mix::Vector3( 0.0f, 10.0f, 0.0f ), 40.0f );
				break;
			}
		}
		break;
	case HUD::CTRL_RESET_B:
		Build();
		break;
	}
}

void HUD::OnComboBox_SelectItemChanged( Utility::UI::ComboBox* pComboBox )
{
	switch( pComboBox->GetID() )
	{
	case HUD::CTRL_LIST_CB:
		Build();
		break;
	}
}

void HUD::Build( void )
{
	switch( m_ListCB.GetSelectedItem() )
	{
	case HUD::BUILDING_PYRAMID:
		BuildPyramid();
		break;
	case HUD::BUILDING_BABEL:
		BuildBabel();
		break;
	case HUD::BUILDING_BILLIARDS:
		BuildBilliards();
		break;
	}
}

void HUD::BuildBilliards( void )
{
	static const Int32 BLOCK_MAX = 8;
	static const Float32 BLOCK_SPACE = 2.2f;

	Int32 blockNum = BLOCK_MAX;
	Float32 z = BLOCK_SPACE * static_cast<Float32>( blockNum ) * 0.5f;

	m_pRoom->Clear();

	while( blockNum > 0 )
	{
		Float32 offset = BLOCK_SPACE * static_cast<Float32>( blockNum ) * -0.5f + BLOCK_SPACE * 0.5f;

		for( Int32 x = 0; x < blockNum; x++ )
		{
			Mix::Vector3 pos;
			Mix::Dynamics::IRigidBody* pRigidBody;

			pos.x = offset + BLOCK_SPACE * static_cast<Float32>( x );
			pos.y = 1.0f;
			pos.z = z;

			pRigidBody = m_pRoom->AddSphere( 1.0f, pos );
			if( pRigidBody != NULL )
			{
				pRigidBody->Deactivate();
			}
		}

		z -= BLOCK_SPACE;
		blockNum--;
	}
}

void HUD::BuildPyramid( void )
{
	static const Int32 BLOCK_MAX = 10;
	static const Float32 BLOCK_SPACE_X = 3.0f;
	static const Float32 BLOCK_SPACE_Y = 2.0f;

	Int32 blockNum = BLOCK_MAX;
	Float32 y = 1.0f;

	m_pRoom->Clear();

	while( blockNum > 0 )
	{
		Float32 offset = BLOCK_SPACE_X * static_cast<Float32>( blockNum ) * -0.5f + 1.5f;

		for( Int32 x = 0; x < blockNum; x++ )
		{
			Mix::Vector3 pos;
			Mix::Dynamics::IRigidBody* pRigidBody;

			pos.x = offset + BLOCK_SPACE_X * static_cast<Float32>( x );
			pos.y = y;
			pos.z = 0.0f;

			pRigidBody = m_pRoom->AddBox( Mix::Vector3( 1.0f, 1.0f, 1.0f ), pos );
			if( pRigidBody != NULL )
			{
				pRigidBody->Deactivate();
			}
		}

		y += BLOCK_SPACE_Y;
		blockNum--;
	}
}

void HUD::BuildBabel( void )
{
	static const Float32 RADIUS = 8.0f;
	static const Int32 CIRCLE_MAX = 16;
	static const Float32 CIRCLE_RAD = MIX_FLOAT_DIV( MIX_2PI, static_cast<Float32>( CIRCLE_MAX ) );
	static const Float32 HALF_CIRCLE_RAD = CIRCLE_RAD * 0.5f;

#ifdef _DEBUG
	static const Int32 STORY = 10;
#else //_DEBUG
	static const Int32 STORY = 30;
#endif //_DEBUG

	Float32 y = 1.0f;
	Float32 radOffset = 0.0f;

	m_pRoom->Clear();

	for( Int32 i = 0; i < STORY; i++ )
	{
		for( Int32 j = 0; j < CIRCLE_MAX; j++ )
		{
			Mix::Quaternion rot;
			Mix::Vector3 pos( RADIUS, y, 0.0f );
			Mix::Dynamics::IRigidBody* pRigidBody;

			rot.SetRotationAxis( Mix::Vector3( 0.0f, 1.0f, 0.0f ), radOffset + CIRCLE_RAD * static_cast<Float32>( j ) );

			pRigidBody = m_pRoom->AddBox( Mix::Vector3( 1.0f, 1.0f, 1.0f ), Mix::Matrix4x4( rot ) * pos );
			if( pRigidBody != NULL )
			{
				pRigidBody->SetWorldRotation( rot );
				pRigidBody->Deactivate();
			}
		}

		radOffset += HALF_CIRCLE_RAD;
		y += 2.0f;
	}
}
