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

#include <coral/core/io/xmi_writer_1.h>

#include <iostream>
#include <fstream>
#include <cmath>

#include <sys/time.h>
#include <unistd.h>

#include <coral/lib/debugstream.h>

int main() {
	coral::init_coral_framework();

	/*
	 * Loads a Model with 2 Classes and a Generalization
	 * in between them.
	 */
	coral::Element* root = coral::io::loadModel("forward_refs.xmi");
	coral_assert(root);

	coral::Language* UML14 = root->__type__()->__language__();

	/* 3 children, 1 from loadModel, 1 for Project,
	   1 for the unref map in Project,
	   BUG 1 from somewhere, equals 7. */
	coral::dlog << coral::DEBUGLEVEL_DEBUG << "root refcount == " << root->get_ref_count() << std::endl;
	coral_assert(root->get_ref_count() == 7);

	coral::Atom* c1 = root->__getSlotByName__("ownedElement")[0];
	coral::Atom* c2 = root->__getSlotByName__("ownedElement")[1];
	coral::Atom* c3 = root->__getSlotByName__("ownedElement")[2];

	/* 1 for parent Model, 1 from Generalization,
	   1 for the unref map,
	   and loadModel should not keep that one ref any longer.
	   equals 3. Generalization has a ref from both classes
	   BUG 1 more, same reason as above I guess...
	*/

	int g = 0;
	int c = 0;
	if (c1->oclIsKindOf(UML14->getElement("Generalization").get())) {
		coral::dlog << coral::DEBUGLEVEL_DEBUG << "Generalization refcount is " << c1->get_ref_count() << std::endl;
		coral_assert(c1->get_ref_count() == 5);
		g++;
	}

	if (c2->oclIsKindOf(UML14->getElement("Generalization").get())) {
		coral::dlog << coral::DEBUGLEVEL_DEBUG << "Generalization refcount is " << c2->get_ref_count() << std::endl;
		coral_assert(c2->get_ref_count() == 5);
		g++;
	}

	if (c3->oclIsKindOf(UML14->getElement("Generalization").get())) {
		coral::dlog << coral::DEBUGLEVEL_DEBUG << "Generalization refcount is " << c3->get_ref_count() << std::endl;
		coral_assert(c3->get_ref_count() == 5);
		g++;
	}

	if (c1->oclIsKindOf(UML14->getElement("Class").get())) {
		coral::dlog << coral::DEBUGLEVEL_DEBUG << "Class refcount is " << c1->get_ref_count() << std::endl;
		coral_assert(c1->get_ref_count() == 4);
		c++;
	}
	if (c2->oclIsKindOf(UML14->getElement("Class").get())) {
		coral::dlog << coral::DEBUGLEVEL_DEBUG << "Class refcount is " << c2->get_ref_count() << std::endl;
		coral_assert(c2->get_ref_count() == 4);
		c++;
	}
	if (c3->oclIsKindOf(UML14->getElement("Class").get())) {
		coral::dlog << coral::DEBUGLEVEL_DEBUG << "Class refcount is " << c3->get_ref_count() << std::endl;
		coral_assert(c3->get_ref_count() == 4);
		c++;
	}
	coral_assert(g == 1);
	coral_assert(c == 2);
	return 0;
}
