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


		#include "metafile/nml.h"
		#include "reflection/c_refl.h"
		#include "memory/nauto_ptr.h"
		#include "assert/nassert.h"


namespace GS {
	namespace NML {
		using namespace Reflection;

//------------------------------------------------------------------------------
bool		GenericObjectFromMetaTag(Tag &t, void *o, Property *o_prop)
{
	NMLTagForeach(pt, t)
		for (int n = 0; o_prop[n].name; ++n)
			if	(pt->name == o_prop[n].name)
			{
				size_t p_prop = (size_t)o + o_prop[n].offset_of;

				switch (o_prop[n].type)
				{
					case Property::BoolProp:
						*(bool *)p_prop = pt->GetBool();
						break;
					case Property::CharProp:
						*(char *)p_prop = (char)pt->GetInteger();
						break;
					case Property::ShortProp:
						*(short *)p_prop = (short)pt->GetInteger();
						break;
					case Property::IntProp:
						*(int *)p_prop = pt->GetInteger();
						break;
					case Property::FloatProp:
						*(float *)p_prop = pt->GetReal();
						break;
					case Property::StringProp:
						*(GS::String *)p_prop = pt->GetString();
						break;
					case Property::EnumProp:
						__ASSERT__(o_prop[n].enum_dict);
						*(int *)p_prop = Enum::fromString(pt->GetString(), o_prop[n].enum_dict);
						break;

					default:
						__ASSERT_ALWAYS__;
						break;
				}
			}

	return true;
}
Tag			*GenericObjectToMetaTag(Tag *t, const void *o, Property *o_prop)
{
	if	(t)
		for (int n = 0; o_prop[n].name; ++n)
		{
			size_t p_prop = (size_t)o + o_prop[n].offset_of;

			switch (o_prop[n].type)
			{
				case Property::BoolProp:
					t->AddChild(o_prop[n].name, *(bool *)p_prop);
					break;
				case Property::CharProp:
					t->AddChild(o_prop[n].name, (int)*(char *)p_prop);
					break;
				case Property::ShortProp:
					t->AddChild(o_prop[n].name, (int)*(short *)p_prop);
					break;
				case Property::IntProp:
					t->AddChild(o_prop[n].name, *(int *)p_prop);
					break;
				case Property::FloatProp:
					t->AddChild(o_prop[n].name, *(float *)p_prop);
					break;
				case Property::StringProp:
					t->AddChild(o_prop[n].name, ((GS::String *)p_prop)->c_str());
					break;
				case Property::EnumProp:
					__ASSERT__(o_prop[n].enum_dict);
					t->AddChild(o_prop[n].name, Enum::toString(*(int *)p_prop, o_prop[n].enum_dict));
					break;

				default:
					__ASSERT_ALWAYS__;
					break;
			}
		}
	return t;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
bool		GenericObjectFromMetaFile(const char *uri, void *obj, Property *obj_prop, const char *root_name)
{
	File file;
	if	(!Parser::Load(uri, file))
		return false;

	if	(Tag *root = file.GetTag(root_name))
		if	(!GenericObjectFromMetaTag(*root, obj, obj_prop))
			return false;

	return true;
}
bool		GenericObjectToMetaFile(const char *uri, const void *obj, Property *obj_prop, const char *root_name)
{
	File file;
	file.AddRoot(GenericObjectToMetaTag(new Tag(root_name), obj, obj_prop));
	return Parser::Save(uri, file);
}
//------------------------------------------------------------------------------

	} //NML
} // GS
