#include <coral/core/Element.h>
#include <coral/core/ElementIterator.h>
#include <coral/coral.h>
#include <coral/core/garbage_collector.h>

#include <iostream>
#include <cmath>

#include <unistd.h>

static coral::Language* uml14;

static void recursivelyCreate(coral::Element* ns, int level, int maxlevel, int children) {
	if (level >= maxlevel) return;
	for (int i = 0; i < children; ++i) {
		std::string name;
		char buf[16];
		snprintf(buf, 16, "%d", i);
		name += "Package ";
		name += buf;
		coral::Element* child = static_cast<coral::Element*>(uml14->getElement("Package")->newAtom());
		dynamic_cast<coral::ElementString*>(child->__getSlotByName__("name")[0])->__setString__(coral::unicodestring(name, true));
		ns->__getSlotByName__("ownedElement").insert(child);
		recursivelyCreate(child, level+1, maxlevel, children);
	}
}

int main() {
	std::cout << "*** Initializing core metamodel..." << std::endl;
	coral::init_coral_framework();
	coral::autounref<coral::Language> _uml14
		= coral::Language::__getLanguage__("UML", 1, 4);
	uml14 = _uml14.get();
	coral::Element* m = static_cast<coral::Element*>(uml14->getElement("Model")->newAtom());

	int levels = 5;
	int children = 5;
	recursivelyCreate(m, 0, levels, children);

	

	int found = 0;
	for (coral::AtomIterator i = m->DFSIterator(); i.hasNext(); ) {
		coral::Element* r = static_cast<coral::Element*>(i.next());
		std::cout << "Got " << r->__str__() << " with name " << dynamic_cast<coral::ElementString*>(r->__getSlotByName__("name")[0])->__getString__() << "." << std::endl;
		++found;
	}

	int n_ok_children = 1;
	int old = 1;
	for (int i = levels; i; --i) {
		old *= children;
		n_ok_children += old;
	}

	std::cout << "Iterated through " << found << ", should be " << n_ok_children << std::endl;
	coral_assert(found == n_ok_children);

	std::cout << "Done!" << std::endl;

	return 0;
}
