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


		#include "core/item.h"
		#include "log/log.h"

		using namespace GS::Core;
		using namespace GS::NML;


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

	item_flags = 0;

	position.Set(0, 0, 0);
	rotation.Set(0, 0, 0);
	scale.Set(1, 1, 1);

	opacity = 1;
	pivot_matrix = Matrix4::IdentityMatrix();
	rorder = Math::rOrder_Default;

	registry.Clear();

	// Parse root tags.
	NMLTagForeach(pt, tag)
	{
				// Legacy support.
				if	(pt->name == "OffsetPosition")
		{
			Vector4 position;
			position.FromMetaTag(*pt);
			pivot_matrix.SetRow(3, position);
		}
		else	if	(pt->name == "OffsetMatrix")
			pivot_matrix.FromMetaTag(*pt);

		else	if	(pt->name == "Position")
			position.FromMetaTag(*pt);
		else	if	(pt->name == "Rotation")
			rotation.FromMetaTag(*pt);
		else	if	(pt->name == "Scale")
			scale.FromMetaTag(*pt);

		else	if	(pt->name == "Target")
			target.FromMetaTag(*pt);
		else	if	(pt->name == "TargetOffsetRotation")
			;

		else	if	(pt->name == "ItemFlag")
		{
			NMLTagForeach(ft, *pt)
			{
				if	(ft->name == "HasTarget")
					item_flags.Set(ItemFlagHasTarget);
				if	(ft->name == "Invisible")
					item_flags.Set(ItemFlagInvisible);
				if	(ft->name == "LinkOnlyPosition")
					item_flags.Set(ItemFlagInheritPositionOnly);
			}
		}

		else	if	(pt->name == "RotationOrder")
		{
			String ro(pt->GetString());

					if	(ro == "ZYX")	rorder = Math::rOrder_ZYX;
			else	if	(ro == "YZX")	rorder = Math::rOrder_YZX;
			else	if	(ro == "ZXY")	rorder = Math::rOrder_ZXY;
			else	if	(ro == "XZY")	rorder = Math::rOrder_XZY;
			else	if	(ro == "YXZ")	rorder = Math::rOrder_YXZ;
			else	if	(ro == "XYZ")	rorder = Math::rOrder_XYZ;
			else	if	(ro == "XY")	rorder = Math::rOrder_XY;

			else	__LOG_W__ << "Unknown rotation order '" << ro << "'.\n";
		}
		else	if	(
						(pt->name == "OrientationQuaternion") ||
						(pt->name == "OrientationMatrix")
					)
			;
		else	if	(pt->name == "Registry")
		{
			NMLTagForeach(child, *pt)
				registry.AddRoot(child->Clone());
		}
		else	__LOG_W__ << "Unknown tag '" << pt->name << "' in <Item>.\n";
	}

	MarkTransformationDirty();
	item_flags.Set(ItemFlagRotationMatrixDirty);

ComputeMatrix();
ComputeInverseMatrix();
	return true;
}
Tag			*Item::AsMetaTag() const
{
	Tag *root = new Tag("Item");
	if	(!root)
		__ERR__(__LOG_E__ << "Could not serialize item. Failed to create root tag.\n", NULL)

	Vector4 NULL_vec(0, 0, 0), NULL_scale(1, 1, 1);

	// Save transformation.
	if	(pivot_matrix != Matrix4::IdentityMatrix())
		root->AddChild(pivot_matrix.AsMetaTag("OffsetMatrix"));
	if	(position != NULL_vec)
		root->AddChild(position.AsMetaTag("Position"));
	if	(rotation != NULL_vec)
		root->AddChild(rotation.AsMetaTag("Rotation"));
	if	(scale != NULL_scale)
		root->AddChild(scale.AsMetaTag("Scale"));

	if	(item_flags.Get() != 0)
		if	(Tag *ft = root->AddChild("ItemFlag"))
		{
			if	(item_flags.IsSet(ItemFlagHasTarget))
				ft->AddChild("HasTarget");
			if	(item_flags.IsSet(ItemFlagInvisible))
				ft->AddChild("Invisible");
			if	(item_flags.IsSet(ItemFlagInheritPositionOnly))
				ft->AddChild("LinkOnlyPosition");
		}

	root->AddChild(target.AsMetaTag("Target"));

	switch (rorder)
	{
		case Math::rOrder_ZYX:	root->AddChild("RotationOrder", "ZYX");		break;
		case Math::rOrder_YZX:	root->AddChild("RotationOrder", "YZX");		break;
		case Math::rOrder_ZXY:	root->AddChild("RotationOrder", "ZXY");		break;
		case Math::rOrder_XZY:	root->AddChild("RotationOrder", "XZY");		break;
		case Math::rOrder_YXZ:	root->AddChild("RotationOrder", "YXZ");		break;
		case Math::rOrder_XYZ:	root->AddChild("RotationOrder", "XYZ");		break;
		case Math::rOrder_XY:	root->AddChild("RotationOrder", "XY");		break;

		default:
			break;
	}

	// Registry.
	Tag *tag_registry = root->AddChild("Registry");
	NMLFileForeach(child, registry)
		tag_registry->AddChild(child->Clone());

	return root;
}
//------------------------------------------------------------------------------
