/* Process the <library_materials> section of COLLADA */
void RCBC_MiniXML_ProcessTextureMaterial(ModelTempory *tempory, mxml_node_t *node) {
	DEBUG_M("Entering function...");

	mxml_node_t* child;
	const char* id;
	const char* url;

	assert(tempory);
	if(!node) {
		return;
	}

	/* Loop through all the material nodes */
	for(node = node->child; node != NULL; node = node->next) {

		if(node->type == MXML_ELEMENT && 
			strcasecmp(node->value.element.name, "material") == 0) {

			id = mxmlElementGetAttr(node, "id");

			for(child = node->child; child != NULL; child = child->next) {
				if(child->type == MXML_ELEMENT && 
					strcasecmp(child->value.element.name, "instance_effect") == 0) {

					url = mxmlElementGetAttr(child, "url");
					DEHASH(url);

					Hookup* material_hookup = NEW(Hookup, (char*)id, NULL);
					ListAdd(tempory->sources, material_hookup);

					Hookup* fx_hookup = NEW(Hookup, (char*)url, &material_hookup->ptr);
					ListAdd(tempory->sinks, fx_hookup);	
				}
			}

		}
	}

	DEBUG_M("Exiting function...");
}
int RCBC_MiniXML_ProcessGeometries_Mesh_Verticies(ModelTempory *tempory, Mesh *mesh, mxml_node_t *xnode) {
	DEBUG_M("Entering function...");

	assert(mesh); 
	assert(xnode);

	mxml_node_t *node;
	char input_id[512];
	const char *source;
	const char *semantic;
	const char *id = mxmlElementGetAttr(xnode, "id");

	for(node = xnode->child; node != NULL; node = node->next) {
		DumpNodeInfo(node);

		if(node->type == MXML_ELEMENT) {
			if(strcasecmp(node->value.element.name, "input") == 0) {
				semantic = mxmlElementGetAttr(node, "semantic");
				source = mxmlElementGetAttr(node, "source");

				DEHASH(source);

				int input_id_len = strlen(id)+strlen(semantic)+2;
				char* input_id = malloc(input_id_len);
				snprintf(input_id, input_id_len, "%s_%s", id, semantic);
				ListAdd(tempory->freeme, input_id); /* free after hookups */

				Hookup* idhookup = NEW(Hookup, (char*)input_id, NULL);
				Hookup* sourcehookup = NEW(Hookup, (char*)source, (void*)&idhookup->ptr);

				ListAdd(tempory->sources, idhookup);
				ListAdd(tempory->sinks, sourcehookup);
			}
		}
	}

	return 0;
}
static int
msdosfs_hashins(struct denode *dep)
{
	struct denode **depp, *deq;

	depp = &dehashtbl[DEHASH(dep->de_dev, dep->de_dirclust,
				 dep->de_diroffset)];
	
	for (deq = *depp; deq; deq = deq->de_next) {
		if (dep->de_dirclust == deq->de_dirclust &&
		    dep->de_diroffset == deq->de_diroffset &&
		    dep->de_dev == deq->de_dev &&
		    deq->de_refcnt != 0) {
			return (EEXIST);
		}
	}

	if ((deq = *depp) != NULL)
		deq->de_prev = &dep->de_next;
	dep->de_next = deq;
	dep->de_prev = depp;
	*depp = dep;
	return (0);
}
static struct denode *
msdosfs_hashget(dev_t dev, uint32_t dirclust, uint32_t diroff)
{
	struct denode *dep;
	struct proc *p = curproc; /* XXX */
       
	for (;;)
		for (dep = dehashtbl[DEHASH(dev, dirclust, diroff)]; ;
		     dep = dep->de_next) {
			if (dep == NULL)
				return (NULL);
			if (dirclust == dep->de_dirclust &&
			    diroff == dep->de_diroffset &&
			    dev == dep->de_dev &&
			    dep->de_refcnt != 0) {
				struct vnode *vp = DETOV(dep);

				if (!vget(vp, LK_EXCLUSIVE, p))
					return (dep);
				break;
			}
		}
	/* NOTREACHED */
}
/**
 * Reads COLLADA mesh triangle data.
 * @param tempory The ModelTempory struct to hold the array.
 * @param mesh The mesh using the triangles
 * @param xnode The XML node containing the data.
 * @return The collada triangles in unsorted form.
 */
UnsortedTriangles* RCBC_MiniXML_ProcessGeometries_Mesh_Triangles(ModelTempory *tempory, Mesh *mesh, mxml_node_t *xnode) {
	DEBUG_M("Entering function...");

	assert(tempory);
	assert(mesh);
	assert(xnode);

	mxml_node_t *node;
	const char* count_s = mxmlElementGetAttr(xnode, "count");
	const char* material = mxmlElementGetAttr(xnode, "material");
	char* source_id;
	int source_id_len;

	int count = atoi(count_s);
	int inputs = 0;

	UnsortedTriangles* triangles = NEW(UnsortedTriangles, count);
	for(node = xnode->child; node != NULL; node = node->next) {
		DumpNodeInfo(node);
		if(node->type == MXML_ELEMENT) {
			if(strcasecmp(node->value.element.name, "input") == 0) {

				const char *semantic = mxmlElementGetAttr(node, "semantic");
				const char *source = mxmlElementGetAttr(node, "source");
				const char *offset_s = mxmlElementGetAttr(node, "offset");
				int offset = atoi(offset_s);

				DEHASH(source);

				void* ptr = NULL;
				inputs++;
				if(strcasecmp(semantic, "VERTEX") == 0) {

					ptr = &(triangles->vertices);
					triangles->vertices_offset = offset;
					triangles->normals_offset = offset;

					#warning ['TODO']: Handle Mayas weirdness
					/* Maya exports the file in a slightly different format
					 * where the vertices structure has both position and
					 * normals rather than them being in trinagles. */
					source_id_len = strlen(source)+strlen("NORMAL")+2;
					source_id = malloc(source_id_len);
					snprintf(source_id, source_id_len, "%s_NORMAL", source);

					/* Add the normals hookup now, the position will be done below */
					Hookup* hookup_normals = NEW(Hookup, (char*)source_id, &triangles->normals);
					ListAdd(tempory->sinks, hookup_normals);

					/* We keep track of strings to free later */
					ListAdd(tempory->freeme, source_id);

					source_id_len = strlen(source)+strlen("POSITION")+2;
					source_id = malloc(source_id_len);
					snprintf(source_id, source_id_len, "%s_POSITION", source);
					ListAdd(tempory->freeme, source_id);

				} else if(strcasecmp(semantic, "NORMAL") == 0) {
					ptr = &(triangles->normals);
					triangles->normals_offset = offset;
					source_id = (char*)source;
				} else if(strcasecmp(semantic, "TEXCOORD") == 0) {
					ptr = &(triangles->texcoords);
					triangles->texcoords_offset = offset;
					source_id = (char*)source;
				}

				Hookup* hookup = NEW(Hookup, (char*)source_id, ptr);
				ListAdd(tempory->sinks, hookup);

			} else if(strcasecmp(node->value.element.name, "p") == 0) {
				triangles->inputs = inputs;
				UnsortedTrianglesAllocateIndices(triangles);
				int value = -1;
				int i = 0;
				char* pch = strtok(node->child->value.opaque, " ");

				while(pch && i < count * inputs * 3) {
					sscanf(pch, "%d", &value);
					triangles->indices[i] = value;
					pch = strtok(NULL, " ");
					i++;
				}
			}
		}
	}

	triangles->inputs = inputs;
	triangles->ptr = (void**)&mesh->triangles;
	ListAdd(tempory->unsorted, triangles);

	if(material != NULL && material[0] != '\0') {
		Hookup* material_hookup = NEW(Hookup, (char*)material, (void*)&triangles->image);
		ListAdd(tempory->sinks, material_hookup);
	}

	return triangles;
}