/*
** 1998-09-12 -	This is GETSIZE, a recursive size computation command. It will assign
**		the size of all contained files to directories.
** 1998-12-19 -	Rewritten to use the new fut_dir_size() function, rather than its own
**		routine. Simpler.
** 1999-03-06 -	Adjusted for the new selection handling.
** 1999-04-09 -	Added the cmd_clearsize() function, implementing the ClearSize command.
*/

#include "gentoo.h"

#include <fcntl.h>

#include "fileutil.h"
#include "dirpane.h"
#include "errors.h"
#include "progress.h"
#include "cmdseq_config.h"

#include "cmd_getsize.h"

/* ----------------------------------------------------------------------------------------- */

typedef struct {
	gboolean	modified;
	gboolean	unselect;		/* Unselect rows when done computing size? */
} OptGetSize;

static OptGetSize	getsize_options;
static CmdCfg		*getsize_cmc = NULL;

/* ----------------------------------------------------------------------------------------- */

/* 1998-09-12 -	Recursive directory sizer.
** 1999-04-09 -	Now also updates the blocks field of the directory's stat buffer.
*/
int cmd_getsize(MainInfo *min, DirPane *src, DirPane *dst, CmdArg *ca)
{
	GSList	*slist, *iter;
	guint	num = 0;
	FUCount	fuc;

	if((slist = dp_get_selection(src)) == NULL)
		return 1;

	pgs_progress_begin(min, "GetSize", PFLG_BUSY_MODE);
	for(iter = slist; iter != NULL; iter = g_slist_next(iter))
	{
		if(S_ISDIR(DP_SEL_LSTAT(iter).st_mode))
		{
			if(fut_dir_size_progress(min, dp_full_name(src, DP_SEL_INDEX(src, iter)), NULL, &fuc))
			{
				DP_SEL_LSTAT(iter).st_size   = fuc.num_bytes;
				DP_SEL_LSTAT(iter).st_blocks = fuc.num_blocks;
				DP_SEL_FLAGS_SET(iter, DPRF_HAS_SIZE);
				num++;
			}
			else
				break;
		}
		if(getsize_options.unselect)
			dp_unselect(src, DP_SEL_INDEX(src, iter));
	}
	pgs_progress_end(min);

	if(num)
	{
		dp_update_stats(src);
		dp_redisplay_preserve(src);
	}
	if(errno)
		err_set(min, errno, "getsize", iter ? DP_SEL_NAME(iter) : NULL);
	else
		err_clear(min);
	err_show(min);

	dp_free_selection(slist);

	return 1;
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-04-09 -	Clear the recursive sizes from all selected directories. Ignores files, but
**		unselects them.
*/
int cmd_clearsize(MainInfo *min, DirPane *src, DirPane *dst, CmdArg *ca)
{
	GSList	*slist, *iter;
	guint	num = 0;

	if((slist = dp_get_selection(src)) == NULL)
		return 1;

	for(iter = slist; iter != NULL; iter = g_slist_next(iter))
	{
		if(S_ISDIR(DP_SEL_LSTAT(iter).st_mode) && DP_SEL_FLAGS_CHK(iter, DPRF_HAS_SIZE))
		{
			const gchar	*name = dp_full_name(src, DP_SEL_INDEX(src, iter));

			if(lstat(name, &DP_SEL_LSTAT(iter)))
				break;
			DP_SEL_FLAGS_CLR(iter, DPRF_HAS_SIZE);
			num++;
		}
		dp_unselect(src, DP_SEL_INDEX(src, iter));
	}

	if(num)
	{
		dp_update_stats(src);
		dp_redisplay_preserve(src);
	}
	if(errno)
		err_set(min, errno, "clearsize", iter ? DP_SEL_NAME(iter) : NULL);
	else
		err_clear(min);
	err_show(min);

	dp_free_selection(slist);

	return 1;
}

/* ----------------------------------------------------------------------------------------- */

/* 1999-04-25 -	Configure the GetSize command's (few) options. */
void cfg_getsize(MainInfo *min)
{
	if(getsize_cmc == NULL)
	{
		getsize_options.modified = FALSE;
		getsize_options.unselect = TRUE;

		getsize_cmc = cmc_config_new("GetSize", &getsize_options);
		cmc_field_add_boolean(getsize_cmc, "modified", NULL, offsetof(OptGetSize, modified));
		cmc_field_add_boolean(getsize_cmc, "unselect", "Unselect Rows When Done?", offsetof(OptGetSize, unselect));
		cmc_config_register(getsize_cmc);
	}
}
