#include "Mix/Tool/CLR/Core/Dynamics/Design/BoundingBox.h"

#include "Mix/Tool/CLR/Core/Dynamics/BoxShape.h"
#include "Mix/Tool/CLR/Core/Dynamics/CapsuleShape.h"
#include "Mix/Tool/CLR/Core/Dynamics/SphereShape.h"

namespace Mix{ namespace Tool{ namespace Dynamics{ namespace Design{

////////////////////////////////////////////////////////////////////////////////////////////////////
// BoundingBox
////////////////////////////////////////////////////////////////////////////////////////////////////

BoundingBox::BoundingBox( int depth ) :
implBoundingBox( new Mix::Tool::Win32::Graphics::BASE_SHAPE() ),
m_bInternalImpl( true ),
m_Depth( depth )
{
	if( implBoundingBox == NULL )
	{
		throw gcnew System::OutOfMemoryException();
	}
}

BoundingBox::BoundingBox( Mix::Tool::Win32::Graphics::BASE_SHAPE* _implBoundingBox ) :
implBoundingBox( _implBoundingBox ),
m_bInternalImpl( false ),
m_Depth( 0 )
{
}

BoundingBox::~BoundingBox( void )
{
	if( ( m_bInternalImpl == true ) &&
		( implBoundingBox != NULL ) )
	{
		delete implBoundingBox;
	}

	implBoundingBox = NULL;
}

Mix::Tool::Win32::Graphics::BASE_SHAPE* BoundingBox::Impl::get( void )
{
	return implBoundingBox;
}

System::String^ BoundingBox::Name::get( void )
{
	if( implBoundingBox == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return gcnew System::String( implBoundingBox->name.c_str() );
}


Mix::Tool::Math::Vector^ BoundingBox::DegreeRotation::get( void )
{
	if( implBoundingBox == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	const D3DXVECTOR3* axis = implBoundingBox->obb.axis;
	D3DXQUATERNION quat = Mix::Tool::Win32::ToQuaternion( axis[0], axis[1], axis[2] );
	D3DXVECTOR3 eulerDeg = Mix::Tool::Win32::ToEulerDegreeZYX( quat );

	return gcnew Mix::Tool::Math::Vector( eulerDeg.x, eulerDeg.y, eulerDeg.z, 1.0f );
}

Mix::Tool::Math::Quaternion^ BoundingBox::Rotation::get( void )
{
	if( implBoundingBox == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	const D3DXVECTOR3* axis = implBoundingBox->obb.axis;
	D3DXQUATERNION rot = Mix::Tool::Win32::ToQuaternion( axis[0], axis[1], axis[2] );

	return gcnew Mix::Tool::Math::Quaternion( rot.x, rot.y, rot.z, rot.w );
}

Mix::Tool::Math::Vector^ BoundingBox::Position::get( void )
{
	if( implBoundingBox == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	const D3DXVECTOR3& pos = implBoundingBox->obb.pos;

	return gcnew Mix::Tool::Math::Vector( pos.x, pos.y, pos.z, 1.0f );
}

Mix::Tool::Math::Vector^ BoundingBox::HalfExtents::get( void )
{
	if( implBoundingBox == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	const D3DXVECTOR3& len = implBoundingBox->obb.len;

	return gcnew Mix::Tool::Math::Vector( len.x, len.y, len.z, 1.0f );
}

int BoundingBox::Depth::get( void )
{
	return m_Depth;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// BoundingBoxCollection
////////////////////////////////////////////////////////////////////////////////////////////////////

BoundingBoxCollection::BoundingBoxCollection( void ) :
m_List( gcnew System::Collections::Generic::List<Mix::Tool::Dynamics::Design::BoundingBox^>() )
{
}

BoundingBoxCollection::~BoundingBoxCollection( void )
{
	if( m_List != nullptr )
	{
		for each( Mix::Tool::Dynamics::Design::BoundingBox^ convex in m_List )
		{
			delete convex;
		}

		m_List->Clear();
	}
}

int BoundingBoxCollection::Count::get( void )
{
	return m_List->Count;
}

Mix::Tool::Dynamics::Design::BoundingBox^ BoundingBoxCollection::default::get( int index )
{
	try
	{
		return m_List[index];
	}
	catch( System::Exception^ )
	{
		throw;
	}
}

System::Collections::IList^ BoundingBoxCollection::DataSource::get( void )
{
	return m_List;
}

int BoundingBoxCollection::IndexOfName( System::String^ name )
{
	int count = m_List->Count;

	for( int i = 0; i < count; i++ )
	{
		if( m_List[i]->Name->Equals( name ) == true )
		{
			return i;
		}
	}

	return -1;
}

System::Collections::IEnumerator^ BoundingBoxCollection::GetEnumerator( void )
{
	return m_List->GetEnumerator();
}

}}}}
