#include "ecdb.h"

int ecdb_source_init(Ecdb_Source *src);
void ecdb_source_add_directory_recursive(Ecdb_Source *parent);

Ecdb_Source *
ecdb_source_new(void)
{
	Ecdb_Source *src;

	src = calloc(1, sizeof(Ecdb_Source));
	if (!src)
		return NULL;
	if (!ecdb_source_init(src))
	{
		FREE(src);
		return NULL;
	}

	return src;
}

int
ecdb_source_init(Ecdb_Source *src)
{
	src->dir = FALSE;
	src->num_children = 0;
	src->children = calloc(1, sizeof(Ecdb_Source));
	if (!src->children)
		return FALSE;
	src->children[src->num_children] = NULL;
	return TRUE;
}

void
ecdb_source_destroy(Ecdb_Source *src)
{
	int i;
	Ecdb_Source *child;

	/* free the non-recursive stuff */
	FREE(src->dst);
	if (src->node)
		iso_node_unref(src->node);

	for (i = 0; src->children[i]; i++)
	{
		child = src->children[i];
		ecdb_source_destroy(child);
	}

	free(src);
}

void
ecdb_source_data_set(Ecdb_Source *src, const char *dst)
{
	if (!src)
		return;

	src->dst = strdup(dst);

	/* Add the files recursively here */
	if (ecore_file_is_dir(src->dst))
	{
		src->dir = TRUE;
		ecdb_source_add_directory_recursive(src);
	}
}

void
ecdb_source_add_directory_recursive(Ecdb_Source *parent)
{
	Ecore_List *files;
	Ecdb_Source *child;
	char *src;

	files = ecore_file_ls(parent->dst);

	while ((src = ecore_list_first_remove(files)))
	{
		child = ecdb_source_new();
		ecdb_source_data_set(child, src);
		ecdb_source_child_append(parent, child);
		free(src);
	}
}

void
ecdb_source_child_append(Ecdb_Source *src, Ecdb_Source *child)
{
	if (src == child)
	{
		printf("Trying to make a parent of itself!\n");
		return;
	}

	src->num_children++;
	src->children = realloc(src->children, sizeof(Ecdb_Source) * 
						(src->num_children + 1));
	src->children[src->num_children - 1] = child;
	src->children[src->num_children] = NULL;
	child->parent = src;
}

/* Basically here we can remove all occurences (who knows why we'd get
 * multiple, but whatever), or just the first.  For now remove the first, and
 * see how that goes
 */
void
ecdb_source_child_remove(Ecdb_Source *src, Ecdb_Source *child)
{
	Ecdb_Source **temp;
	int i, cidx, f;

	if (src == child)
	{
		printf("Trying to remove oneself\n");
		return;
	}

	temp = calloc(src->num_children, sizeof(Ecdb_Source));
	temp[src->num_children - 1] = NULL;

	cidx = f = 0;
	for (i = 0; src->children[i]; i++)
	{
		if ((src->children[i] == child) && (!f))
		{
			f++;
			continue;
		}
		temp[cidx] = src->children[i];
		cidx++;
	}

	FREE(src->children);
	src->children = temp;
	src->num_children--;
	child->parent = NULL;
}

void
ecdb_source_add_children_rec(Ecdb_Source *parent, IsoImage *image)
{
	IsoDir *cd = NULL;
	Ecdb_Source *cs;
	int i;

	if ((!parent) || (!image))
		return;

	i = 0;
	while ((cs = parent->children[i]))
	{
		if (cs->dir)
		{
			iso_tree_add_new_dir(ISO_DIR(parent->node),
					ecore_file_file_get(cs->dst),
					&cd);
			cs->node = ISO_NODE(cd);
			/* If the source has children, find the node from above
			 * (if applicable), and recursively add to it */
			if (cs->num_children > 0)
			{
				ecdb_source_add_children_rec(cs, image);
			}

		}
		
		/* file */
		else
		{
			iso_tree_add_node(image, ISO_DIR(parent->node),
							cs->dst, NULL);
		}
		i++;
	}
}

/* proj->files should only have children */
BurnSource *
ecdb_image_project(Ecdb_Burn_Project *proj)
{
	IsoImage *image;
	Ecdb_Source *c;
	IsoWriteOpts *opts;
	BurnSource *data_src, *fifo_src;

	if ((!proj->files) || (!proj->files->num_children))
		return NULL;

	/* To handle already-suplied image files */
	if (proj->files->num_children == 1)
	{
		efreet_mime_init();
		c = proj->files->children[0];
		if ((!ecore_file_is_dir(c->dst)) &&
				(!strcmp(efreet_mime_type_get(c->dst),
					 "application/x-cd-image")))
		{
			data_src = burn_file_source_new(c->dst, NULL);
			goto FIFO_CREATE;
		}
		efreet_mime_shutdown();
	}

	/* Otherwise we have a bunch of files */
	if (!iso_image_new(proj->volume_id, &image))
	{
		printf("Failed to create image!\n");
		return NULL;
	}

	/* Set all ids */
	if (proj->publisher_id)
		iso_image_set_publisher_id(image, proj->publisher_id);
	if (proj->data_preparer_id)
		iso_image_set_data_preparer_id(image,
						proj->data_preparer_id);
	if (proj->system_id)
		iso_image_set_system_id(image, proj->system_id);
	if (proj->application_id)
		iso_image_set_application_id(image, proj->application_id);
	if (proj->copywrite_id)
		iso_image_set_copyright_file_id(image, proj->copywrite_id);
	if (proj->abstract_id)
		iso_image_set_abstract_file_id(image, proj->abstract_id);
	if (proj->biblio_id)
		iso_image_set_biblio_file_id(image, proj->biblio_id);

	if (!iso_write_opts_new(&opts, 2))
	{
		printf("Failed to create writing options!\n");
		iso_image_unref(image);
		return NULL;
	}

	/* And some write opts stuff */
	iso_write_opts_set_iso_level(opts, proj->iso_level);
	iso_write_opts_set_joliet(opts, proj->use_joliet);
	iso_write_opts_set_rockridge(opts, proj->use_rockridge);
	iso_write_opts_set_iso1999(opts, proj->iso1990);
	iso_write_opts_set_appendable(opts, proj->multi);
	
	iso_tree_set_follow_symlinks(image, proj->follow_symlinks);
	iso_tree_set_ignore_hidden(image, proj->ignore_hidden);
	iso_tree_set_ignore_special(image, proj->ignore_special);

	/* actually fill image with some files now */
	proj->files->node = ISO_NODE(iso_image_get_root(image));
	ecdb_source_add_children_rec(proj->files, image);
	
	/* Make the burn source here */
	iso_image_create_burn_source(image, opts, &data_src);
	iso_write_opts_free(opts);
	iso_image_unref(image);

	/* And, convert to fifo */
FIFO_CREATE:
	fifo_src = burn_fifo_source_new(data_src,
			proj->fifo_chunksize, proj->fifo_chunks, 0);
	burn_source_free(data_src);
	return fifo_src;
}

