/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* vim: set ts=8 sts=8 sw=8 noet : */

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>

#include "libisofs.h"
#include "tree.h"
#include "util.h"
#include "volume.h"
#include "eltorito.h"

struct iso_volset*
iso_volset_new(struct iso_volume *vol, const char *id)
{
	struct iso_volset *volset = calloc(1, sizeof(struct iso_volset));

	volset->volset_size = 1;
	volset->refcount = 1;
	volset->volume = malloc(sizeof(void *));
	volset->volume[0] = vol;
	volset->volset_id = strdup(id);
	return volset;
}

void
iso_volset_ref(struct iso_volset *volset)
{
	++volset->refcount;
}

void
iso_volset_free(struct iso_volset *volset)
{
	if (--volset->refcount < 1) {
		int i;
		for (i = 0; i < volset->volset_size; i++) {
			iso_volume_free(volset->volume[i]);
		}
		free(volset->volume);
		free(volset->volset_id);
		free(volset);
	}
}

struct iso_volume *
iso_volset_get_volume(struct iso_volset *volset, int volnum)
{
	assert(volset);
	if (volnum < volset->volset_size)
		return volset->volume[volnum];
	else
		return NULL;
}

struct iso_volume*
iso_volume_new(const char *volume_id,
	       const char *publisher_id,
	       const char *data_preparer_id)
{
	return iso_volume_new_with_root(volume_id,
					publisher_id,
					data_preparer_id,
					NULL);
}

struct iso_volume*
iso_volume_new_with_root(const char *volume_id,
			 const char *publisher_id,
			 const char *data_preparer_id,
			 struct iso_tree_node_dir *root)
{
	struct iso_volume *volume;

	volume = calloc(1, sizeof(struct iso_volume));
	volume->refcount = 1;

	volume->root = root ? root : iso_tree_new_root();

	if (volume_id != NULL)
		volume->volume_id = strdup(volume_id);
	if (publisher_id != NULL)
		volume->publisher_id = strdup(publisher_id);
	if (data_preparer_id != NULL)
		volume->data_preparer_id = strdup(data_preparer_id);
	return volume;
}

void
iso_volume_free(struct iso_volume *volume)
{
	/* Only free if no references are in use. */
	if (--volume->refcount < 1) {
		iso_tree_free( (struct iso_tree_node*) volume->root);

		free(volume->volume_id);
		free(volume->publisher_id);
		free(volume->data_preparer_id);
		free(volume->system_id);
		free(volume->application_id);
		free(volume->copyright_file_id);
		free(volume->abstract_file_id);
		free(volume->biblio_file_id);
		if (volume->bootcat) 
			el_torito_boot_catalog_free(volume->bootcat);
		free(volume);
	}
}

struct iso_tree_node_dir *
iso_volume_get_root(const struct iso_volume *volume)
{
	assert(volume);
	return volume->root;
}

void iso_volume_set_volume_id(struct iso_volume *volume,
			      const char *volume_id)
{
	assert(volume);
	free(volume->volume_id);
	volume->volume_id = strdup(volume_id);
}

const char *
iso_volume_get_volume_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->volume_id;
}

void iso_volume_set_publisher_id(struct iso_volume *volume,
				 const char *publisher_id)
{
	assert(volume);
	free(volume->publisher_id);
	volume->publisher_id = strdup(publisher_id);
}

const char *
iso_volume_get_publisher_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->publisher_id;
}

void iso_volume_set_data_preparer_id(struct iso_volume *volume,
				     const char *data_preparer_id)
{
	assert(volume);
	free(volume->data_preparer_id);
	volume->data_preparer_id = strdup(data_preparer_id);
}

const char *
iso_volume_get_data_preparer_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->data_preparer_id;
}

void iso_volume_set_system_id(struct iso_volume *volume,
				     const char *system_id)
{
	assert(volume);
	free(volume->system_id);
	volume->system_id = strdup(system_id);
}

const char *
iso_volume_get_system_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->system_id;
}

void iso_volume_set_application_id(struct iso_volume *volume,
				     const char *application_id)
{
	assert(volume);
	free(volume->application_id);
	volume->application_id = strdup(application_id);
}

const char *
iso_volume_get_application_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->application_id;
}

void iso_volume_set_copyright_file_id(struct iso_volume *volume,
				     const char *copyright_file_id)
{
	assert(volume);
	free(volume->copyright_file_id);
	volume->copyright_file_id = strdup(copyright_file_id);
}

const char *
iso_volume_get_copyright_file_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->copyright_file_id;
}

void iso_volume_set_abstract_file_id(struct iso_volume *volume,
				     const char *abstract_file_id)
{
	assert(volume);
	free(volume->abstract_file_id);
	volume->abstract_file_id = strdup(abstract_file_id);
}

const char *
iso_volume_get_abstract_file_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->abstract_file_id;
}

void iso_volume_set_biblio_file_id(struct iso_volume *volume,
				     const char *biblio_file_id)
{
	assert(volume);
	free(volume->biblio_file_id);
	volume->biblio_file_id = strdup(biblio_file_id);
}

const char *
iso_volume_get_biblio_file_id(struct iso_volume *volume)
{
	assert(volume);
	return volume->biblio_file_id;
}

struct iso_tree_node *
iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
{
	struct iso_tree_node *node;
	struct iso_tree_node_dir *dir;
	char *ptr, *brk_info, *component;

	/* get the first child at the root of the volume
	 * that is "/" */
	dir = iso_volume_get_root(volume);
	node = (struct iso_tree_node *)dir;
	if (!strcmp(path, "/"))
		return node;

	if (!dir->nchildren)
		return NULL;

	ptr = strdup(path);

	/* get the first component of the path */
	component=strtok_r(ptr, "/", &brk_info);
	while (component) {
		size_t max;
		size_t i;
		
		if ( !ISO_ISDIR(node) ) {
			node=NULL;
			break;
		}
		dir = (struct iso_tree_node_dir *)node;

		/* search among all the children of this directory if this path component exists */
		max=dir->nchildren;
		for (i=0; i < max; i++) {
			if (!strcmp(component, dir->children[i]->name)) {
				node=dir->children[i];
				break;
			}
		}

		/* see if a node could be found */
		if (i==max) {
			node=NULL;
			break;
		}

		component=strtok_r(NULL, "/", &brk_info);
	}

	free(ptr);
	return node;
}

//
//struct iso_tree_node *
//iso_tree_volume_add_path(struct iso_volume *volume,
//					 const char *disc_path,
//					 const char *path)
//{
//	char *tmp;
//	struct iso_tree_node *node;
//	struct iso_tree_node *parent_node;
//
//	tmp=strdup(disc_path);
//	parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
//	free(tmp);
//
//	if (!parent_node)
//		return NULL;
//
//	node = iso_tree_radd_dir(parent_node, path);
//	if (!node)
//		return NULL;
//
//	tmp=strdup(disc_path);
//	iso_tree_node_set_name(node, basename(tmp));
//	free(tmp);
//
//	return node;
//}
//
//struct iso_tree_node *
//iso_tree_volume_add_new_dir(struct iso_volume *volume,
//	 				      const char *disc_path)
//{
//	char *tmp;
//	struct iso_tree_node *node;
//	struct iso_tree_node *parent_node;
//
//	tmp=strdup(disc_path);
//	parent_node = iso_tree_volume_path_to_node(volume, dirname(tmp));
//	free(tmp);
//
//	if (!parent_node)
//		return NULL;
//
//	tmp=strdup(disc_path);
//	node = iso_tree_add_new_dir(parent_node, basename(tmp));
//	free(tmp);
//
//	return node;
//}