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


		#include "motion/quaternion_channel.h"
		#include "metafile/nml.h"
		#include "alloc/ialloc.h"
		#include "log/log.h"

		using namespace GS;
		using NML::Tag;


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

	Clear();

	// Parse root tags.
	NMLTagForeach(pt, tag)
	{
		if	(pt->name == "BinaryKeys")
		{
			Tag *count_tag = pt->GetTag("Count"), *data_tag = pt->GetTag("Data");

			if	(count_tag && data_tag)
			{
				float *data = (float *)data_tag->GetValue().GetBinaryBuffer(), *p_data = data;

				if	(data)
				{
					int count = count_tag->GetInteger();
					for	(int n = 0; n < count; ++n)
					{
						QuaternionKey *key = new QuaternionKey;

						key->t = Time::fromSec(*p_data++);
						key->q.x = *p_data++;
						key->q.y = *p_data++;
						key->q.z = *p_data++;
						key->q.w = *p_data++;

						keys.Add(key);
					}
				}
			}
		}
		else	if	(pt->name == "Keys")
		{
			NMLTagForeach(st, *pt)
				if	(st->name == "Key")
				{
					const char *p = st->GetString();
					if	(!p)
						__LOG_W__ << "Invalid key tag while parsing quaternion channel.\n";

					else
					{
						//-------------------------------------------------------------------------------------------
						#define	SEEK_CHAR(v)																		\
						p = String::strfindchar(p, (v));															\
						if	(!p[0])																					\
							__ERR__(__LOG_W__ << "Mangled keyframe tag while parsing quaternion channel.\n", false)	\
						p++;																						\
						//-------------------------------------------------------------------------------------------

						QuaternionKey *key = new QuaternionKey;

						key->t = Time::fromSec(String::atof(p, NULL, false));
						SEEK_CHAR(':');

						key->q.x = String::atof(p, NULL, false);
						SEEK_CHAR(',');
						key->q.y = String::atof(p, NULL, false);
						SEEK_CHAR(',');
						key->q.z = String::atof(p, NULL, false);
						SEEK_CHAR(',');
						key->q.w = String::atof(p, NULL, false);

						keys.Add(key);
					}
				}
		}
		else	__LOG_W__ << "Unknown tag '" << pt->name << "' in <QChannel>.\n";
	}
	return true;
}
Tag			*QuaternionChannel::AsMetaTag()
{
	Tag *root = new Tag("QChannel");
	if	(!root)
		__ERR__(__LOG_E__ << "Could not create quaternion channel root tag to serialize.\n", NULL)

	if	(keys.GetCount())
		if	(Tag *kf_tag = root->AddChild("BinaryKeys"))
		{
			kf_tag->AddChild("Count", (int)keys.GetCount());	// Legacy support.

			float *kf_array = new float[5 * keys.GetCount()], *p_kf = kf_array;

			for	(uint n = 0; n < keys.GetCount(); n++)
			{
				*p_kf++ = keys[n]->t.toSec();
				*p_kf++ = keys[n]->q.x;
				*p_kf++ = keys[n]->q.y;
				*p_kf++ = keys[n]->q.z;
				*p_kf++ = keys[n]->q.w;
			}

			kf_tag->AddChild("Data", (uchar *)kf_array, 5 * 4 * keys.GetCount());
			_safe_delete_array(kf_array);
		}

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