// This file is part of the Coral project.
// Please read the copyright notice in the LICENSE file.

#include <coral/core/DCE_UUID.h>

#include <coral/coral.h>
#include <coral/core/CorePrimitives.h>
#include <coral/core/ElementDefinition.h>
#include <coral/core/PrimitiveProperties.h>

NAMESPACE_BEGIN(coral);
NAMESPACE_BEGIN(CORE);

static bool has_loaded = false;

coral::Language* language;

/* A Name is special; it tells us that we can use the string
 * to give a nice representation for the user.
 */
coral::DatatypeDefinition* Name;
coral::DatatypeDefinition* String;
coral::EnumerationDefinition* Boolean;
coral::DatatypeDefinition* Integer;
coral::DatatypeDefinition* UnlimitedInteger; // N/A
coral::DatatypeDefinition* UnlimitedReal; // N/A
coral::DatatypeDefinition* Float; // Same as Double
coral::DatatypeDefinition* Double;
coral::DatatypeDefinition* coralPyObj; // Can hold a Python object

coral::ElementDefinition* AnyElement; // Topmost element
coral::ElementDefinition* AnyAbstractElement;
coral::ElementDefinition* PresentationElement;

static const char* cc0[] = { "core_false", "core_true", NULL };
static const coral::util::mmcreator::Enumeration enum0 = { &Boolean, "Boolean", cc0 };
/*
 * All our enumerations
 */
static const coral::util::mmcreator::Enumeration* enums[] = {
	&enum0,
	NULL
};

static const coral::util::mmcreator::Datatype dtypes[] = {
	{ &String, "String" },
	{ &UnlimitedInteger, "UnlimitedInteger" },
	{ &Integer, "Integer" },
	{ &UnlimitedReal, "UnlimitedReal" },
	{ &Float, "Float" },
	{ &Double, "Double" },
	{ &coralPyObj, "coralPyObj" },
	{ &Name, "Name" },
	{ NULL, NULL }
};
	
/*
 * All our metamodel elements
 */
static const coral::util::mmcreator::Element elems[] = {
	{ &AnyElement, "AnyElement" },
	{ &AnyAbstractElement, "AnyAbstractElement" },
	{ &PresentationElement, "PresentationElement" },
	{ NULL, NULL }
};

/*
 * All our subclass <-> superclass relations
 * They have to be given as names due to c++ restrictions.
 */
static const coral::util::mmcreator::SubAndSuper bases[] = {
	{ "AnyAbstractElement", "AnyElement" },
	{ "PresentationElement", "AnyElement" }, 
	{ "Integer", "UnlimitedInteger" },
	{ "Float", "UnlimitedReal" },
	{ "Double", "UnlimitedReal" },
	{ "Name", "String" },
	{ NULL, NULL }
};

/*
 * All our slots
 */
static const coral::util::mmcreator::Feature slots[] = {
	/*
	 * Note, we add the Property
	 * CORE::AnyElement.xmi_extension
	 * later in coral_init_framework()
	 *
	 */
	{ NULL, NULL, NULL, NULL, 0, 0, 0 }
};

/*
 * The initialization routines
 * - Create all metamodel elements 
 * - create metamodel slots and insert them into respective metamodel
 *   elements
 */
bool init_language() throw () {

	if (has_loaded) return true;

	try {
		if (!language) language = new coral::Language(std::string("CORE"), 0, 1);

		coral::util::mmcreator::create_elems(language, enums, dtypes, elems, bases, slots);
		coral_assert(Boolean->size() == 2);

		language->setRoot(AnyElement);
		language->setXMLNS("http://www.abo.fi/CORE/0.1");
	} catch (...) {

		return false;
	}

	has_loaded = true;
	return true;
}

NAMESPACE_END();
NAMESPACE_END();

