#include "hud.h"

#include "Mix/Graphics/ITexture.h"
#include "Mix/Scene/ICamera.h"

const Int32 HUD::SMOOTH_RANGE_TABLE[Mix::Scene::BLUR::TYPE_MAX][2] =
{
	{ 0, 0, },
	{ 1, 16, },
	{ 1, 16, },
	{ 1, 64, },
	{ 4, 64, },
};

HUD::HUD( void ) :
m_pCamera( NULL ),
m_pTex( NULL )
{
}

HUD::~HUD( void )
{
}

void HUD::Initialize( const Mix::Point& screenSize, Mix::Scene::ICamera* pCamera, Mix::Graphics::ITexture* pTex )
{
	MIX_ASSERT( pCamera != NULL );
	MIX_ASSERT( pTex != NULL );

	const Mix::Scene::CAMERA_CONFIG& camSettings = pCamera->GetConfig();
	const Mix::Scene::ICamera::CHROMATISM_SETTINGS& setting = pCamera->GetChromatismSettings();
	Int32 itemY = 16;

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

	MIX_ADD_REF( pCamera );
	m_pCamera = pCamera;

	MIX_ADD_REF( pTex );
	m_pTex = pTex;

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

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

	m_BlurTable[Mix::Scene::BLUR::T_NONE] = Mix::Scene::BLUR::NONE();
	m_BlurTable[Mix::Scene::BLUR::T_KS_3x3] = Mix::Scene::BLUR::KS_3x3( 1 );
	m_BlurTable[Mix::Scene::BLUR::T_KS_5x5] = Mix::Scene::BLUR::KS_5x5( 1 );
	m_BlurTable[Mix::Scene::BLUR::T_GAUSSIAN] = Mix::Scene::BLUR::GAUSSIAN( 4.0f );
	m_BlurTable[Mix::Scene::BLUR::T_GAUSSIAN_EX] = Mix::Scene::BLUR::GAUSSIAN_EX( 16 );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// General
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_EnabledCB.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_EnabledCB.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_EnabledCB.SetText( L"Enabled" );
	m_EnabledCB.SetState( m_pCamera->IsChromatismEnabled() );
	m_EnabledCB.Initialize( this, HUD::CTRL_ENABLED_CB );

#ifdef _DEBUG
	itemY += HUD::ITEM_Y_STEP;

	m_DebugCB.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_DebugCB.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_DebugCB.SetText( L"Debug" );
	m_DebugCB.SetState( False );
	m_DebugCB.Initialize( this, HUD::CTRL_DEBUG_CB );
	itemY += HUD::ITEM_Y_STEP;
#else //_DEBUG
	itemY += HUD::ITEM_Y_STEP;
#endif //_DEBUG

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Bokeh
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_BokehL.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_BokehL.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_BokehL.SetText( L"Bokeh :" );
	m_BokehL.Initialize( this, HUD::CTRL_BOKEH_L );
	itemY += HUD::ITEM_Y_STEP;

	m_SmplCB.Initialize( this, HUD::CTRL_SMPL_CB );
	m_SmplCB.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_SmplCB.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_SmplCB.AddItem( Mix::Scene::RSMPL_DEFAULT, L"Default( Copy )" );
	m_SmplCB.AddItem( Mix::Scene::RSMPL_DOWN2X, L"Down2x" );
	m_SmplCB.AddItem( Mix::Scene::RSMPL_DOWN4X, L"Down4x" );
	m_SmplCB.SetSelectedItem( camSettings.caSmplRes, False );
	itemY += HUD::ITEM_Y_STEP;

	m_BlurCB.Initialize( this, HUD::CTRL_BLUR_TYPE_CB );
	m_BlurCB.SetPosition( Mix::Point( HUD::ITEM_X1, itemY ) );
	m_BlurCB.SetSize( Mix::Point( HUD::ITEM_WIDTH1, HUD::ITEM_HEIGHT1 ) );
	m_BlurCB.AddItem( Mix::Scene::BLUR::T_NONE, L"NONE" );
	m_BlurCB.AddItem( Mix::Scene::BLUR::T_KS_3x3, L"KERNEL_3x3" );
	m_BlurCB.AddItem( Mix::Scene::BLUR::T_KS_5x5, L"KERNEL_5x5" );
	m_BlurCB.AddItem( Mix::Scene::BLUR::T_GAUSSIAN, L"GAUSSIAN" );
	m_BlurCB.AddItem( Mix::Scene::BLUR::T_GAUSSIAN_EX, L"GAUSSIAN_EX" );
	m_BlurCB.SetSelectedItem( setting.blur.GetType(), False );

	m_BlurSI.SetPosition( Mix::Point( HUD::ITEM_X2, itemY ) );
	m_BlurSI.SetSize( Mix::Point( HUD::ITEM_WIDTH2, HUD::ITEM_HEIGHT2 ) );
	m_BlurSI.SetText( L"" );
	m_BlurSI.SetRange( HUD::SMOOTH_RANGE_TABLE[setting.blur.GetType()][0], HUD::SMOOTH_RANGE_TABLE[setting.blur.GetType()][1] );
	m_BlurSI.SetValue( HUD::GetSmoothValue( setting.blur ) );
	m_BlurSI.SetEanbled( setting.blur.GetType() != Mix::Scene::BLUR::T_NONE );
	m_BlurSI.SetStep( 1 );
	m_BlurSI.Initialize( this, HUD::CTRL_BLUR_VALUE_SI );
	itemY += HUD::ITEM_YY_STEP;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// Distortion
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_DistoL.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_DistoL.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_DistoL.SetText( L"Distortion :" );
	m_DistoL.Initialize( this, HUD::CTRL_BOKEH_L );
	itemY += HUD::ITEM_Y_STEP;

	m_KSF.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_KSF.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_KSF.SetText( L"k" );
	m_KSF.SetRange( -1.0f, +1.0f );
	m_KSF.SetStep( 0.01f );
	m_KSF.SetValue( setting.distortion.k );
	m_KSF.Initialize( this, HUD::CTRL_K_SF );
	itemY += HUD::ITEM_Y_STEP;

	m_KCubeSF.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_KCubeSF.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_KCubeSF.SetText( L"kCube" );
	m_KCubeSF.SetRange( -1.0f, +1.0f );
	m_KCubeSF.SetStep( 0.01f );
	m_KCubeSF.SetValue( setting.distortion.kCube );
	m_KCubeSF.Initialize( this, HUD::CTRL_K_CUBE_SF );
	itemY += HUD::ITEM_Y_STEP;

	m_DriftSF.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_DriftSF.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_DriftSF.SetText( L"Weight" );
	m_DriftSF.SetRange( 1.0f, 10.0f );
	m_DriftSF.SetStep( 0.01f );
	m_DriftSF.SetValue( setting.weight );
	m_DriftSF.Initialize( this, HUD::CTRL_WEIGHT_SF );
	itemY += HUD::ITEM_Y_STEP;

	m_DistSF.SetPosition( Mix::Point( HUD::ITEM_X, itemY ) );
	m_DistSF.SetSize( Mix::Point( HUD::ITEM_WIDTH, HUD::ITEM_HEIGHT ) );
	m_DistSF.SetText( L"Dist" );
	m_DistSF.SetRange( 0.0f, 100.0f );
	m_DistSF.SetStep( 0.1f );
	m_DistSF.SetValue( setting.fiEndZ - setting.fiStartZ );
	m_DistSF.Initialize( this, HUD::CTRL_DIST_SF );
	itemY += HUD::ITEM_Y_STEP;
}

void HUD::OnDispose( void )
{
	MIX_RELEASE( m_pTex );
	MIX_RELEASE( m_pCamera );
}

void HUD::OnCheckBox_Click( Utility::UI::CheckBox* pCheckBox )
{
#ifdef _DEBUG
	UInt32 debDrawFlags = m_pCamera->Debug_GetDrawFlags();
#endif //_DEBUG

	switch( pCheckBox->GetID() )
	{
	case HUD::CTRL_ENABLED_CB:
		m_pCamera->SetChromatismEnabled( pCheckBox->GetState() );
		break;
#ifdef _DEBUG
	case HUD::CTRL_DEBUG_CB:
		if( MIX_TESTBIT( debDrawFlags, Mix::Scene::DDF_PP_CHROMATISM ) == Mix::Scene::DDF_PP_CHROMATISM )
		{
			MIX_RESETBIT( debDrawFlags, Mix::Scene::DDF_PP_CHROMATISM );
		}
		else
		{
			MIX_SETBIT( debDrawFlags, Mix::Scene::DDF_PP_CHROMATISM );
		}
		m_pCamera->Debug_SetDrawFlags( debDrawFlags );
		break;
#endif //_DEBUG
	}
}

void HUD::OnSlider_ValueChanged( Utility::UI::SliderF* pSlider )
{
	Mix::Scene::ICamera::CHROMATISM_SETTINGS settings = m_pCamera->GetChromatismSettings();

	switch( pSlider->GetID() )
	{
	case HUD::CTRL_K_SF:
		settings.distortion.kCube = pSlider->GetValue();
		m_pCamera->SetChromatismSettings( settings );
		break;
	case HUD::CTRL_K_CUBE_SF:
		settings.distortion.k = pSlider->GetValue();
		m_pCamera->SetChromatismSettings( settings );
		break;
	case HUD::CTRL_WEIGHT_SF:
		settings.weight = pSlider->GetValue();
		m_pCamera->SetChromatismSettings( settings );
		break;
	case HUD::CTRL_DIST_SF:
		settings.fiEndZ = settings.fiStartZ + pSlider->GetValue();
		m_pCamera->SetChromatismSettings( settings );
		break;
	}
}

void HUD::OnSlider_ValueChanged( Utility::UI::SliderI* pSlider )
{
	Mix::Scene::ICamera::CHROMATISM_SETTINGS settings = m_pCamera->GetChromatismSettings();

	switch( pSlider->GetID() )
	{
	case HUD::CTRL_BLUR_VALUE_SI:
		HUD::SetSmoothValue( settings.blur, pSlider->GetValue() );
		m_BlurTable[settings.blur.GetType()] = settings.blur;
		m_pCamera->SetChromatismSettings( settings );
		break;
	}
}

void HUD::OnComboBox_SelectItemChanged( Utility::UI::ComboBox* pComboBox )
{
	Mix::Scene::CAMERA_CONFIG camConfig = m_pCamera->GetConfig();
	Mix::Scene::ICamera::CHROMATISM_SETTINGS settings = m_pCamera->GetChromatismSettings();

	Mix::Scene::RENDERER_SAMPLING_RESOLUTION smplRes;

	switch( pComboBox->GetID() )
	{
	case HUD::CTRL_SMPL_CB:
		smplRes = static_cast<Mix::Scene::RENDERER_SAMPLING_RESOLUTION>( pComboBox->GetSelectedItem() );
		if( camConfig.caSmplRes != smplRes )
		{
			camConfig.caSmplRes = smplRes;
			m_pCamera->SetConfig( camConfig );
		}
		break;

	case HUD::CTRL_BLUR_TYPE_CB:
		settings.blur = m_BlurTable[pComboBox->GetSelectedItem()];
		m_pCamera->SetChromatismSettings( settings );
		m_BlurSI.SetRange( HUD::SMOOTH_RANGE_TABLE[settings.blur.GetType()][0], HUD::SMOOTH_RANGE_TABLE[settings.blur.GetType()][1] );
		m_BlurSI.SetValue( HUD::GetSmoothValue( settings.blur ) );
		m_BlurSI.SetEanbled( settings.blur.GetType() != Mix::Scene::BLUR::T_NONE );
		break;
	}
}

Int32 HUD::GetSmoothValue( const Mix::Scene::BLUR& blur )
{
	Int32 ret = 0;

	switch( blur.GetType() )
	{
	case Mix::Scene::BLUR::T_NONE:
		ret = 0;
		break;
	case Mix::Scene::BLUR::T_KS_3x3:
		ret = blur.GetIntValue();
		break;
	case Mix::Scene::BLUR::T_KS_5x5:
		ret = blur.GetIntValue();
		break;
	case Mix::Scene::BLUR::T_GAUSSIAN:
		ret = static_cast<Int32>( blur.GetFloatValue() );
		break;
	case Mix::Scene::BLUR::T_GAUSSIAN_EX:
		ret = blur.GetIntValue();
		break;
	}

	return ret;
}

void HUD::SetSmoothValue( Mix::Scene::BLUR& blur, Int32 value )
{
	switch( blur.GetType() )
	{
	case Mix::Scene::BLUR::T_KS_3x3:
		blur = Mix::Scene::BLUR::KS_3x3( value );
		break;
	case Mix::Scene::BLUR::T_KS_5x5:
		blur = Mix::Scene::BLUR::KS_5x5( value );
		break;
	case Mix::Scene::BLUR::T_GAUSSIAN:
		blur = Mix::Scene::BLUR::GAUSSIAN( static_cast<Float32>( value ) );
		break;
	case Mix::Scene::BLUR::T_GAUSSIAN_EX:
		blur = Mix::Scene::BLUR::GAUSSIAN_EX( value );
		break;
	}
}
