/* === S Y N F I G ========================================================= */
/*!	\file valuenode_registry.cpp
**	\brief Valuenode automatic registry
**
**	\legal
**	Copyright (c) 2016 caryoscelus
**
**	This package is free software; you can redistribute it and/or
**	modify it under the terms of the GNU General Public License as
**	published by the Free Software Foundation; either version 2 of
**	the License, or (at your option) any later version.
**
**	This package is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**	General Public License for more details.
**	\endlegal
*/
/* ========================================================================= */

/* === H E A D E R S ======================================================= */

#include "valuenode_registry.h"

#include "general.h"
#include "localization.h"

/* === U S I N G =========================================================== */

using namespace synfig;

/* === G L O B A L S ======================================================= */

ValueNodeRegistry::Book* ValueNodeRegistry::book_ = NULL;

/* === M E T H O D S ======================================================= */

ValueNodeRegistry::Book&
ValueNodeRegistry::book()
{
	if (!book_)
		book_ = new Book();
	return *book_;
}

String
ValueNodeRegistry::localize_name(const String &local_name)
	{ return _(local_name.c_str()); }

void
ValueNodeRegistry::register_node_type(const String &name, const String &local_name, ReleaseVersion version, Factory factory, CheckType check_type)
{
	book()[name].local_name = local_name;
	book()[name].release_version = version;
	book()[name].factory = factory;
	book()[name].check_type = check_type;
}

bool
ValueNodeRegistry::cleanup()
{
	if (book_)
	{
		delete book_;
		book_ = NULL;
	}
	return true;
}

LinkableValueNode::Handle
ValueNodeRegistry::create(const String &name, const ValueBase& x)
{
	// forbid creating a node if class is not registered
	if(!ValueNodeRegistry::book().count(name))
		return NULL;

	if (!check_type(name, x.get_type()))
	{
		error(_("Bad type: ValueNode '%s' doesn't accept type '%s'"), ValueNodeRegistry::book()[name].local_name.c_str(), x.get_type().description.local_name.c_str());
		return NULL;
	}

	return ValueNodeRegistry::book()[name].factory(x, NULL);
}

bool
ValueNodeRegistry::check_type(const String &name, Type &x)
{
	// the BoneRoot and Duplicate ValueNodes are exceptions - we don't want the
	// user creating them for themselves, so check_type() fails for
	// them even when it is valid
	if((name == "bone_root" && x == type_bone_object) ||
	   (name == "duplicate" && x == type_real))
		return true;

	if(!ValueNodeRegistry::book().count(name) || !ValueNodeRegistry::book()[name].check_type)
		return false;
	return ValueNodeRegistry::book()[name].check_type(x);
}
