/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include "physic/physic_shape.h"
		#include "math/matrix3.h"
		#include "metafile/nml.h"
		#include "log/log.h"

		using namespace GS::NML;
		using namespace GS::S3D;


//------------------------------------------------------------------------------
bool				PhysicShape::FromMetaTag(Tag &tag)
{
	if	((tag.name != "GColShape") && (tag.name != "PhysicShape"))
		__ERR__(__LOG_E__ << "Could not parse physic shape, incorrect root tag (" << tag.name << ").\n", false)

	type = TypeNone;
	mass = Units::Kg(1.f);

	// Parse root tags.
	String	_mss("Mass"), _damp("Damping"), _sfr("StaticFriction"), _dfr("DynamicFriction"), _res("Restitution"),
			_plm("Polymesh"), _msh("Mesh"), _dms("Dimensions"), _rds("Radius"), _pos("Position"), _ori("Orientation"), _rot("Rotation"),
			_act("Active"), _type("Type"), _aso("AnisotropicFriction"), _vsf("VStaticFriction"), _vdf("VDynamicFriction"),
			_scl("Scale");

	NMLTagForeach(pt, tag)
	{
		if	(pt->name == _type)
		{
			String _type(pt->GetString());

					if	(_type == "Box")
					type = TypeBox;
			else	if	(_type == "Sphere")
					type = TypeSphere;
			else	if	(_type == "Convex")
					type = TypeConvex;
			else	if	(_type == "Cylinder")
					type = TypeCylinder;
			else	if	(_type == "Cone")
					type = TypeCone;
			else	if	(_type == "Capsule")
					type = TypeCapsule;
			else	if	(_type == "Mesh")
					type = TypeMesh;
			else	if	(_type == "Heightmap")
					type = TypeHeightmap;

			// GCol shapes.
			else	if	(_type == "Cuboid")
					type = TypeBox;
			else	if	(_type == "PolyMesh")
					type = TypeMesh;

			else	type = TypeNone;
		}

		else	if	(pt->name == _pos)
				position.FromMetaTag(*pt);
		else	if	(pt->name == _rot)
				rotation.FromMetaTag(*pt);
		else	if	(pt->name == _ori)
		{
			Matrix3 orientation_matrix;
			orientation_matrix.FromMetaTag(*pt);
			rotation = orientation_matrix.AsEuler();
		}
		else	if	(pt->name == _scl)
				scale.FromMetaTag(*pt);
		else	if	(pt->name == _dms)
				dimensions.FromMetaTag(*pt);
		else	if	(pt->name == _rds)
				dimensions.x = pt->GetReal();

		else	if	((pt->name == _plm) || (pt->name == _msh))
				path = pt->GetString();

		else	if	(pt->name == _mss)
				mass = pt->GetReal();

		else	if	(pt->name == _sfr)
				static_friction = pt->GetReal();
		else	if	(pt->name == _dfr)
				dynamic_friction = pt->GetReal();
		else	if	(pt->name == _res)
				restitution = pt->GetReal();

	#if 	1
		else	if	(pt->name == "Active")
			;
	#endif

		else	__LOG_W__ << "Unknown tag '" << pt->name << "' in <PhysicShape>.\n";
	}
	return true;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
Tag					*PhysicShape::AsMetaTag() const
{
	Tag *root = new Tag("PhysicShape");
	if	(!root)
		__ERR__(__LOG_E__ << "Could not create collision shape root tag to serialize.\n", NULL)

	if	(type != TypeNone)
	{
		String _type;
		switch (type)
		{
			case TypeBox:		_type = "Box";			break;
			case TypeSphere:	_type = "Sphere";		break;
			case TypeConvex:	_type = "Convex";		break;
			case TypeCylinder:	_type = "Cylinder";		break;
			case TypeCone:		_type = "Cone";			break;
			case TypeCapsule:	_type = "Capsule";		break;
			case TypeMesh:		_type = "Mesh";			break;
			case TypeHeightmap:	_type = "Heightmap";	break;

			default:
				_type = "None";
				break;
		}
		root->AddChild("Type", _type.c_str());
	}

	root->AddChild(position.AsMetaTag("Position"));
	root->AddChild(rotation.AsMetaTag("Rotation"));
	root->AddChild(scale.AsMetaTag("Scale"));
	root->AddChild(dimensions.AsMetaTag("Dimensions"));

	switch (type)
	{
		case TypeMesh:
		case TypeConvex:
			if	(!path.IsEmpty())
				root->AddChild("Mesh", path.c_str());
			break;

		default:
			break;
	}

	if	(mass != Units::Kg(1))
		root->AddChild("Mass", mass);

	root->AddChild("StaticFriction", static_friction);
	root->AddChild("DynamicFriction", dynamic_friction);
	root->AddChild("Restitution", restitution);
	return root;
}
//------------------------------------------------------------------------------
