/*
 *	Prints a list of all Devices or information for a specific
 *	Device.
 *
 *	If the -m argument is specified then the Device is mounted.
 *	If the -u argument is specified then the Device is unmounted.
 *	If the -e argument is specified then the Device is ejected.
 */

#include <glib.h>
#include <endeavour2.h>


static void print_device_info(edv_device_struct *d);

static edv_device_struct *match_device(
	edv_context_struct *ctx, const gchar *path
);

static void list_devices(edv_context_struct *ctx);

static void mount_device(edv_context_struct *ctx, edv_device_struct *d);
static void unmount_device(edv_context_struct *ctx, edv_device_struct *d);
static void eject_device(edv_context_struct *ctx, edv_device_struct *d);


/*
 *	Prints information about the specified Device.
 */
static void print_device_info(edv_device_struct *d)
{
	gulong used;

	if(d == NULL)
	    return;

	if(d->blocks_total > d->blocks_free)
	    used = d->blocks_total - d->blocks_free;
	else
	    used = 0l;

	g_print(
	    "Device: \"%s\" (%s)\n",
	    d->name, EDV_DEVICE_IS_MOUNTED(d) ? "Mounted" : "Unmounted"
	);
	g_print("\tFilesystem: %s\n", EDVDeviceGetFSNameFromType(d->fs_type));
	g_print("\tDevice Path: %s\n", d->device_path);
	g_print("\tMount Path: %s\n", d->mount_path);
	if(EDV_DEVICE_IS_MOUNTED(d))
	{
	    g_print(
		"\tCapacity Used: %ld kb (%ld mb) %i%%\n",
		used, used / 1000l,
		(d->blocks_total > 0l) ?
		    (gint)((gfloat)used / (gfloat)d->blocks_total * 100.0f) : 0
	    );
	    g_print("\tCapacity Total: %ld kb (%ld mb)\n",
		d->blocks_total, d->blocks_total / 1000l
	    );
	}
}


/*
 *	Matches a Device by the specified mount path or device path.
 */
static edv_device_struct *match_device(
	edv_context_struct *ctx, const gchar *path
)
{
	gint total;
	edv_device_struct *d, **list = EDVDevicesList(ctx, &total);

	/* Update device mount states and stats */
	EDVDevicesListUpdateMountStates(list, total);
	EDVDevicesListUpdateStats(list, total);      

	/* Match Device by mount path*/
	d = EDVDeviceListMatchMountPath(list, total, NULL, path);
	if(d != NULL)
	    return(d);

	/* Match Device by device path*/
	d = EDVDeviceListMatchDevicePath(list, total, NULL, path);
	if(d != NULL)
	    return(d);

	return(NULL);
}

/*
 *	Prints a list of all Devices.
 */
static void list_devices(edv_context_struct *ctx)
{
	gint i, total;
	edv_device_struct **list = EDVDevicesList(ctx, &total);

	/* Update device mount states and stats */
	EDVDevicesListUpdateMountStates(list, total);
	EDVDevicesListUpdateStats(list, total);

	/* Print information on all devices */
	for(i = 0; i < total; i++)
	    print_device_info(list[i]);
}


/*
 *	Mounts the specified Device.
 */
static void mount_device(edv_context_struct *ctx, edv_device_struct *d)
{
	if(EDVDeviceMount(ctx, d, TRUE))
	    g_printerr("%s\n", EDVMountGetError());
}

/*
 *	Unmounts the specified Device.
 */
static void unmount_device(edv_context_struct *ctx, edv_device_struct *d)
{
	if(EDVDeviceUnmount(ctx, d, TRUE))
	    g_printerr("%s\n", EDVMountGetError());
}

/*
 *	Ejects the specified Device.
 */
static void eject_device(edv_context_struct *ctx, edv_device_struct *d)
{
	if(EDVDeviceEject(ctx, d))
	    g_printerr("%s\n", EDVMountGetError());
}


int main(int argc, char *argv[])
{
	edv_context_struct *ctx = EDVContextNew();
	EDVContextLoadConfigurationFile(ctx, NULL);


	if(argc > 2)
	{
	    const gchar	*op = argv[1],
			*path = argv[2];
	    edv_device_struct *d = match_device(ctx, path);
	    if(d != NULL)
	    {
		if(!g_strcasecmp(op, "-m"))
		    mount_device(ctx, d);
		else if(!g_strcasecmp(op, "-u"))
		    unmount_device(ctx, d);
		else if(!g_strcasecmp(op, "-e"))
		    eject_device(ctx, d);
		else
		    g_printerr("%s: Invalid argument.\n", op);
	    }
	    else
		g_printerr("%s: No such device.\n", path);
	}
	else if(argc > 1)
	{
	    const gchar *path = argv[1];
	    edv_device_struct *d = match_device(ctx, path);
	    if(d != NULL)
		print_device_info(d);
	    else
		g_printerr("%s: No such device.\n", path);
	}
	else
	{
	    const gchar *prog = argv[0];

	    /* Since no arguments given then print list of MIME Types */
	    list_devices(ctx);

	    g_print(
"\n\
Usage: %s [mount_path|device_path]\n\
       %s -m [mount_path|device_path]\n\
       %s -u [mount_path|device_path]\n\
       %s -e [mount_path|device_path]\n",
		prog, prog, prog, prog
	    );
	}

	EDVContextSync(ctx);
	EDVContextDelete(ctx);

	return(0);
}
