#include "pointDialog.h"

#include "Mix/Graphics/IManager.h"
#include "Mix/Scene/IManager.h"
#include "Mix/Scene/IRenderer.h"
#include "Mix/Scene/ICamera.h"
#include "Mix/Scene/IPointLight.h"

PointDialog::PointDialog( void ) :
m_pCamera( NULL )
{
}

PointDialog::~PointDialog( void )
{
}

void PointDialog::Initialize( Mix::Scene::IManager* pSceneManager, Mix::Scene::IRenderer* pSceneRenderer, Mix::Scene::ICamera* pCamera )
{
	MIX_ASSERT( pSceneManager );
	MIX_ASSERT( pSceneRenderer );

	MIX_ADD_REF( pCamera );
	m_pCamera = pCamera;

	for( UInt32 i = 0; i < 4; i++ )
	{
		Mix::Scene::IPointLight* pLight = NULL;

		if( pSceneManager->CreatePointLight( &pLight ) == True )
		{
			Mix::Matrix4x4 mat;
			Mix::Vector3 pos;

			mat.SetRotationY( MIX_TO_RAD( 45.0f ) + MIX_TO_RAD( 90.0f ) * static_cast<Float32>( i ) );
			pos = mat * Mix::Vector3( 0.0f, 0.2f, 7.8f );

			pLight->SetEnabled( True );
			pLight->SetPosition( pos );
			pLight->SetColor( Mix::Vector4( 1.0f, 0.6f, 0.4f, 1.0f ) );
			pLight->SetAttenuation( 0.5f, 0.0f, 0.0f );
			pLight->SetRadius( 0.9f, 6.0f );

			pSceneRenderer->AddPointLight( pLight );

			m_LightList.push_back( pLight );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 自身の設定
	////////////////////////////////////////////////////////////////////////////////////////////////////

	SetCaption( L"Point" );
	SetPosition( Mix::Vector2( 256.0f, 128.0f ) );
	SetSize( Mix::Point( PointDialog::DLG_WIDTH, PointDialog::DLG_HEIGHT ) );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// コントロールの追加
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_ASSERT( m_LightList.size() > 0 );

	Mix::Scene::IPointLight* pLight = m_LightList.front();
	Boolean bDisplayBounds = ( MIX_TESTBIT( m_pCamera->Debug_GetDrawFlags(), Mix::Scene::DDF_POINTLIGHT_BOUNDS ) == Mix::Scene::DDF_POINTLIGHT_BOUNDS );
	const Mix::Vector4& color = pLight->GetColor();
	Int32 itemY = PointDialog::ITEM_Y;

	m_EnabledCB.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_EnabledCB.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_EnabledCB.SetText( L"Enabled" );
	m_EnabledCB.SetState( pLight->IsEnabled() );
	m_EnabledCB.Initialize( this, PointDialog::CTRL_ENABLED_CB );
	itemY += PointDialog::ITEM_Y_STEP;

#ifdef _DEBUG

	m_DisplayBoundsCB.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_DisplayBoundsCB.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_DisplayBoundsCB.SetText( L"Display bounds" );
	m_DisplayBoundsCB.SetState( bDisplayBounds );
	m_DisplayBoundsCB.Initialize( this, PointDialog::CTRL_DISPLAY_BOUNDS_CB );
	itemY += PointDialog::ITEM_Y_STEP;

#endif //_DEBUG

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

	m_ColorC.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_ColorC.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_ColorC.SetText( L"" );
	m_ColorC.SetAlphaEnabled( True );
	m_ColorC.SetValue( color );
	m_ColorC.Initialize( this, PointDialog::CTRL_COLOR_C );
	itemY += PointDialog::ITEM_Y_STEP;

	m_RedSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_RedSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_RedSF.SetText( L"R" );
	m_RedSF.SetRange( 0.0f, 1.0f );
	m_RedSF.SetStep( 0.01f );
	m_RedSF.SetValue( color.r );
	m_RedSF.Initialize( this, PointDialog::CTRL_RED_SF );
	itemY += PointDialog::ITEM_Y_STEP;

	m_GreenSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_GreenSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_GreenSF.SetText( L"G" );
	m_GreenSF.SetRange( 0.0f, 1.0f );
	m_GreenSF.SetStep( 0.01f );
	m_GreenSF.SetValue( color.g );
	m_GreenSF.Initialize( this, PointDialog::CTRL_GREEN_SF );
	itemY += PointDialog::ITEM_Y_STEP;

	m_BlueSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_BlueSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_BlueSF.SetText( L"B" );
	m_BlueSF.SetRange( 0.0f, 1.0f );
	m_BlueSF.SetStep( 0.01f );
	m_BlueSF.SetValue( color.b );
	m_BlueSF.Initialize( this, PointDialog::CTRL_BLUE_SF );
	itemY += PointDialog::ITEM_Y_STEP;

	m_AlphaSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_AlphaSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_AlphaSF.SetText( L"A" );
	m_AlphaSF.SetRange( 0.0f, 1.0f );
	m_AlphaSF.SetStep( 0.01f );
	m_AlphaSF.SetValue( color.a );
	m_AlphaSF.Initialize( this, PointDialog::CTRL_ALPHA_SF );
	itemY += PointDialog::ITEM_Y_STEP;

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

	m_LAttenSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_LAttenSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_LAttenSF.SetText( L"AttenL" );
	m_LAttenSF.SetRange( 0.0f, 1.0f );
	m_LAttenSF.SetStep( 0.1f );
	m_LAttenSF.SetValue( pLight->GetLinearAttenuation() );
	m_LAttenSF.Initialize( this, PointDialog::CTRL_L_ATTEN_SF );
	itemY += PointDialog::ITEM_Y_STEP;

	m_QAttenSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_QAttenSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_QAttenSF.SetText( L"AttenQ" );
	m_QAttenSF.SetRange( 0.0f, 1.0f );
	m_QAttenSF.SetStep( 0.01f );
	m_QAttenSF.SetValue( pLight->GetQuadraticAttenuation() );
	m_QAttenSF.Initialize( this, PointDialog::CTRL_Q_ATTEN_SF );
	itemY += PointDialog::ITEM_Y_STEP;

	m_EAttenSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_EAttenSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_EAttenSF.SetText( L"AttenE" );
	m_EAttenSF.SetRange( 0.0f, 1.0f );
	m_EAttenSF.SetStep( 0.001f );
	m_EAttenSF.SetValue( pLight->GetExponentAttenuation() );
	m_EAttenSF.Initialize( this, PointDialog::CTRL_E_ATTEN_SF );
	itemY += PointDialog::ITEM_Y_STEP;

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

	m_InnerRadiusSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_InnerRadiusSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_InnerRadiusSF.SetText( L"Inner" );
	m_InnerRadiusSF.SetRange( 0.0f, 10.0f );
	m_InnerRadiusSF.SetStep( 0.1f );
	m_InnerRadiusSF.SetValue( pLight->GetInnerRadius() );
	m_InnerRadiusSF.Initialize( this, PointDialog::CTRL_INNER_RADIUS_SF );
	itemY += PointDialog::ITEM_Y_STEP;

	m_OuterRadiusSF.SetPosition( Mix::Point( PointDialog::ITEM_X, itemY ) );
	m_OuterRadiusSF.SetSize( Mix::Point( PointDialog::ITEM_WIDTH, PointDialog::ITEM_HEIGHT ) );
	m_OuterRadiusSF.SetText( L"Outer" );
	m_OuterRadiusSF.SetRange( 0.0f, 7.0f );
	m_OuterRadiusSF.SetStep( 0.1f );
	m_OuterRadiusSF.SetValue( pLight->GetOuterRadius() );
	m_OuterRadiusSF.Initialize( this, PointDialog::CTRL_OUTER_RADIUS_SF );
	itemY += PointDialog::ITEM_Y_STEP;
}

void PointDialog::OnDispose( void )
{
	if( m_LightList.size() > 0 )
	{
		for( PointDialog::LightList::iterator it = m_LightList.begin(); it != m_LightList.end(); ++it )
		{
			MIX_RELEASE( ( *it ) );
		}

		m_LightList.clear();
	}

	MIX_RELEASE( m_pCamera );
}

void PointDialog::OnCheckBox_Click( Utility::UI::CheckBox* pCheckBox )
{
	UInt32 ddFlags = m_pCamera->Debug_GetDrawFlags();

	PointDialog::LightList::iterator it_begin = m_LightList.begin();
	PointDialog::LightList::iterator it_end = m_LightList.end();
	PointDialog::LightList::iterator it;

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

	switch( pCheckBox->GetID() )
	{
	case PointDialog::CTRL_ENABLED_CB:
		for( it = it_begin; it != it_end; ++it )
		{
			( *it )->SetEnabled( pCheckBox->GetState() );
		}
		break;

	case PointDialog::CTRL_DISPLAY_BOUNDS_CB:
		if( pCheckBox->GetState() == True )
		{
			MIX_SETBIT( ddFlags, Mix::Scene::DDF_POINTLIGHT_BOUNDS );
		}
		else
		{
			MIX_RESETBIT( ddFlags, Mix::Scene::DDF_POINTLIGHT_BOUNDS );
		}
		break;
	}

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

	m_pCamera->Debug_SetDrawFlags( ddFlags );
}

void PointDialog::OnSlider_ValueChanged( Utility::UI::SliderF* pSlider )
{
	PointDialog::LightList::iterator it_begin = m_LightList.begin();
	PointDialog::LightList::iterator it_end = m_LightList.end();
	PointDialog::LightList::iterator it;

	Mix::Vector4 color;

	switch( pSlider->GetID() )
	{
	case PointDialog::CTRL_RED_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			color = ( *it )->GetColor();
			color.r = pSlider->GetValue();
		}
		m_ColorC.SetValue( color );
		break;
	case PointDialog::CTRL_GREEN_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			color = ( *it )->GetColor();
			color.g = pSlider->GetValue();
		}
		m_ColorC.SetValue( color );
		break;
	case PointDialog::CTRL_BLUE_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			color = ( *it )->GetColor();
			color.b = pSlider->GetValue();
		}
		m_ColorC.SetValue( color );
		break;
	case PointDialog::CTRL_ALPHA_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			color = ( *it )->GetColor();
			color.a = pSlider->GetValue();
		}
		m_ColorC.SetValue( color );
		break;

	case PointDialog::CTRL_L_ATTEN_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			( *it )->SetAttenuation( pSlider->GetValue(), ( *it )->GetQuadraticAttenuation(), ( *it )->GetExponentAttenuation() );
		}
		break;
	case PointDialog::CTRL_Q_ATTEN_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			( *it )->SetAttenuation( ( *it )->GetLinearAttenuation(), pSlider->GetValue(), ( *it )->GetExponentAttenuation() );
		}
		break;
	case PointDialog::CTRL_E_ATTEN_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			( *it )->SetAttenuation( ( *it )->GetLinearAttenuation(), ( *it )->GetQuadraticAttenuation(), pSlider->GetValue() );
		}
		break;

	case PointDialog::CTRL_INNER_RADIUS_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			( *it )->SetRadius( pSlider->GetValue(), ( *it )->GetOuterRadius() );
		}
		break;
	case PointDialog::CTRL_OUTER_RADIUS_SF:
		for( it = it_begin; it != it_end; ++it )
		{
			( *it )->SetRadius( ( *it )->GetInnerRadius(), pSlider->GetValue() );
		}
		break;
	}
}

void PointDialog::OnColor_ValueChanged( Utility::UI::Color* pColor )
{
	PointDialog::LightList::iterator it_begin = m_LightList.begin();
	PointDialog::LightList::iterator it_end = m_LightList.end();
	PointDialog::LightList::iterator it;

	switch( pColor->GetID() )
	{
	case PointDialog::CTRL_COLOR_C:
		for( it = it_begin; it != it_end; ++it )
		{
			( *it )->SetColor( pColor->GetValue() );
		}
		break;
	}
}
