#include "Mix/Tool/Win32/Core/Graphics/MaterialShader.h"

#include "Mix/Tool/Win32/Core/Graphics/Manager.h"
#include "Mix/Tool/Win32/Core/Graphics/VertexLayout.h"
#include "Mix/Tool/Win32/Core/Graphics/VertexShader.h"
#include "Mix/Tool/Win32/Core/Graphics/PixelShader.h"

namespace Mix{ namespace Tool{ namespace Win32{ namespace Graphics{

MaterialShader::MaterialShader( void )
{
	unsigned int i;
	unsigned int j;

	for( i = 0; i < Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX; i++ )
	{
		m_VertexShaderID[i] = 0;
		m_pVertexLayout[i] = NULL;
		m_pSelectVS[i] = NULL;

		for( j = 0; j < Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX; j++ )
		{
			m_pVertexShader[i][j] = NULL;
		}
	}

	m_PixelShaderID = 0;
	m_pSelectPS = NULL;

	for( i = 0; i < Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX; i++ )
	{
		m_pPixelShader[i] = NULL;
	}
}

MaterialShader::~MaterialShader( void )
{
	unsigned int i;
	unsigned int j;

	for( i = 0; i < Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX; i++ )
	{
		MIX_RELEASE( m_pVertexLayout[i] );
		MIX_RELEASE( m_pSelectVS[i] );

		for( j = 0; j < Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX; j++ )
		{
			MIX_RELEASE( m_pVertexShader[i][j] );
		}
	}

	for( i = 0; i < Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX; i++ )
	{
		MIX_RELEASE( m_pPixelShader[i] );
	}

	MIX_RELEASE( m_pSelectPS );
}

void MaterialShader::Compile( unsigned int flags )
{
	Mix::Tool::Win32::Graphics::Manager* pManager;

	unsigned int simpleFlags = MIX_TEST_BIT( flags, MCF_SIMPLE_MASK );
	unsigned int blendFlags = MIX_TEST_BIT( flags, MCF_BLEND_MASK );

	unsigned int vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX] = { 0 };
	unsigned int pixelShaderID = 0;

	Mix::Tool::Win32::Graphics::VertexLayout* pVertexLayout[Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX] = { NULL };
	Mix::Tool::Win32::Graphics::VertexShader* pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX][Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX] = { NULL };
	Mix::Tool::Win32::Graphics::PixelShader* pPixelShader[Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX] = { NULL };

	Mix::Tool::Win32::Graphics::VertexShader* pSelectVS[Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX] = { NULL };
	Mix::Tool::Win32::Graphics::PixelShader* pSelectPS = NULL;

	unsigned int i;
	unsigned int j;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// マネージャを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バーテックスシェーダー( シンプル )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TEST_BIT( simpleFlags, MCF_SIMPLE_VERTEX ) == MCF_SIMPLE_VERTEX )
	{
		pManager->MEP_CreateVertexShader(	simpleFlags,
											vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE],
											&( pVertexLayout[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] ),
											&( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE][Mix::Tool::Win32::Graphics::MAPPING_COLOR] ),
											&( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE][Mix::Tool::Win32::Graphics::MAPPING_MASK] ),
											&( pSelectVS[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] ) );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バーテックスシェーダー( ブレンド )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TEST_BIT( blendFlags, MCF_BLEND_VERTEX ) == MCF_BLEND_VERTEX )
	{
		if( pManager->MEP_CreateVertexShader(	blendFlags,
												vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_BLEND],
												&( pVertexLayout[Mix::Tool::Win32::Graphics::VERTEX_BLEND] ),
												&( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_BLEND][Mix::Tool::Win32::Graphics::MAPPING_COLOR] ),
												&( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_BLEND][Mix::Tool::Win32::Graphics::MAPPING_MASK] ),
												&( pSelectVS[Mix::Tool::Win32::Graphics::VERTEX_BLEND] ) ) == false )
		{
			vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] = 0;
			MIX_RELEASE( pVertexLayout[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] );
			MIX_RELEASE( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE][Mix::Tool::Win32::Graphics::MAPPING_COLOR] );
			MIX_RELEASE( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE][Mix::Tool::Win32::Graphics::MAPPING_MASK] );
			MIX_RELEASE( pSelectVS[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ピクセルシェーダー
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( pManager->MEP_CreatePixelShader(	flags,
											pixelShaderID,
											&pPixelShader[Mix::Tool::Win32::Graphics::MAPPING_COLOR],
											&pPixelShader[Mix::Tool::Win32::Graphics::MAPPING_MASK],
											&pSelectPS ) == false )
	{
		vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_BLEND] = 0;
		MIX_RELEASE( pVertexLayout[Mix::Tool::Win32::Graphics::VERTEX_BLEND] );
		MIX_RELEASE( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_BLEND][Mix::Tool::Win32::Graphics::MAPPING_COLOR] );
		MIX_RELEASE( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_BLEND][Mix::Tool::Win32::Graphics::MAPPING_MASK] );
		MIX_RELEASE( pSelectVS[Mix::Tool::Win32::Graphics::VERTEX_BLEND] );

		vertexShaderID[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] = 0;
		MIX_RELEASE( pVertexLayout[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] );
		MIX_RELEASE( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE][Mix::Tool::Win32::Graphics::MAPPING_COLOR] );
		MIX_RELEASE( pVertexShader[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE][Mix::Tool::Win32::Graphics::MAPPING_MASK] );
		MIX_RELEASE( pSelectVS[Mix::Tool::Win32::Graphics::VERTEX_SIMPLE] );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// シェーダーを設定しなおす
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( i = 0; i < Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX; i++ )
	{
		m_VertexShaderID[i] = vertexShaderID[i];

		MIX_RELEASE( m_pVertexLayout[i] );
		m_pVertexLayout[i] = pVertexLayout[i];

		MIX_RELEASE( m_pSelectVS[i] );
		m_pSelectVS[i] = pSelectVS[i];

		for( j = 0; j < Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX; j++ )
		{
			MIX_RELEASE( m_pVertexShader[i][j] );
			m_pVertexShader[i][j] = pVertexShader[i][j];
		}
	}

	m_PixelShaderID = pixelShaderID;

	for( i = 0; i < Mix::Tool::Win32::Graphics::MAPPING_TYPE_MAX; i++ )
	{
		MIX_RELEASE( m_pPixelShader[i] );
		m_pPixelShader[i] = pPixelShader[i];
	}

	MIX_RELEASE( m_pSelectPS );
	m_pSelectPS = pSelectPS;
}

void MaterialShader::Register( void )
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// マネージャを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	Mix::Tool::Win32::Graphics::Manager* pManager = Manager::GetInstance();
	if( pManager == NULL )
	{
		return;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バーテックスシェーダーを登録
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( unsigned int i = 0; i < Mix::Tool::Win32::Graphics::VERTEX_TYPE_MAX; i++ )
	{
		if( m_VertexShaderID[i] != 0 )
		{
			pManager->MEP_RegisterVertexShader( m_VertexShaderID[i] );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ピクセルシェーダーを登録
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_PixelShaderID != 0 )
	{
		pManager->MEP_RegisterPixelShader( m_PixelShaderID );
	}
}

unsigned int MaterialShader::GetVertexShaderID( Mix::Tool::Win32::Graphics::VERTEX_TYPE type ) const
{
	MIX_ASSERT( type != Mix::Tool::Win32::Graphics::VERTEX_UNKNOWN );

	return m_VertexShaderID[type];
}

unsigned int MaterialShader::GetPixelShaderID( void ) const
{
	return m_PixelShaderID;
}

Mix::Tool::Win32::Graphics::VertexLayout* MaterialShader::GetVertexLayoutPtr( Mix::Tool::Win32::Graphics::VERTEX_TYPE type ) const
{
	MIX_ASSERT( type != Mix::Tool::Win32::Graphics::VERTEX_UNKNOWN );

	return m_pVertexLayout[type];
}

Mix::Tool::Win32::Graphics::VertexShader* MaterialShader::GetVertexShaderPtr( Mix::Tool::Win32::Graphics::VERTEX_TYPE vertexType, Mix::Tool::Win32::Graphics::MAPPING_TYPE mappingType ) const
{
	MIX_ASSERT( vertexType != Mix::Tool::Win32::Graphics::VERTEX_UNKNOWN );

	return m_pVertexShader[vertexType][mappingType];
}

Mix::Tool::Win32::Graphics::PixelShader* MaterialShader::GetPixelShaderPtr( Mix::Tool::Win32::Graphics::MAPPING_TYPE mappingType ) const
{
	return m_pPixelShader[mappingType];
}

Mix::Tool::Win32::Graphics::VertexShader* MaterialShader::GetSelectVertexShaderPtr( Mix::Tool::Win32::Graphics::VERTEX_TYPE vertexType ) const
{
	MIX_ASSERT( vertexType != Mix::Tool::Win32::Graphics::VERTEX_UNKNOWN );

	return m_pSelectVS[vertexType];
}

Mix::Tool::Win32::Graphics::PixelShader* MaterialShader::GetSelectPixelShaderPtr( void ) const
{
	return m_pSelectPS;
}

Mix::Tool::Win32::Object::TYPE MaterialShader::GetType( void ) const
{
	return Mix::Tool::Win32::Object::GRAPHICS__MATERIAL_SHADER;
}

}}}}
