/*
** 1998-05-21 -	Everybody's favourite, the native delete command. Dangerous stuff if you don't
**		quite know what you're doing!
** 1998-05-29 -	Converted to use the new cmd_generic module, looks a lot better and actually IS
**		better, too. Gives user more control.
** 1998-07-28 -	Turned on the NODST flag in the cmd_generic call. Really should have done that
**		earlier! Hm. I guess I need more beta testing.
** 1998-09-18 -	Rewrote large parts of this one. Now uses the standard overwrite protection/
**		confirmation module, rather than rolling its own. No longer uses the generic
**		command interface.
** 1998-12-15 -	Commented out the progress reporting, since it didn't work well.
** 1999-03-06 -	Adjusted for the new selection/dirrow access methods.
** 1999-05-29 -	Restructured. Now exports two utility functions handy to use from elsewhere.
*/

#include "gentoo.h"
#include "errors.h"
#include "dialog.h"
#include "fileutil.h"
#include "dirpane.h"
#include "overwrite.h"
#include "progress.h"

#include "cmd_delete.h"

#define	CMD_ID	"delete"

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

/* 1999-05-29 -	Delete a plain file. This is capable of removing anything that is not a
**		directory. For that, use del_delete_directory().
*/
gboolean del_delete_file(MainInfo *min, const gchar *path)
{
	gint	ret;

	ret = unlink(path);

	if(ret || errno)
		err_set(min, errno, CMD_ID, path);
	return (ret == 0) ? TRUE : FALSE;
}

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

/* 1999-05-29 -	Delete a directory. */
gboolean del_delete_directory(MainInfo *min, const gchar *path)
{
	gchar		old_dir[PATH_MAX];
	DIR		*dir;
	struct dirent	*de;
	struct stat	stat;

	if(rmdir(path) == 0)					/* If it's empty, this saves time. */
		return 1;
	else if((errno == ENOTEMPTY) || (errno == EEXIST))	/* Wasn't empty. Enter and traverse. */
	{
		err_clear(min);					/* Error was expected, so ignore it. */
		if(fut_cd(path, old_dir, sizeof old_dir))
		{
			if((dir = opendir(".")) != NULL)
			{
				while((de = readdir(dir)) != NULL)
				{
					pgs_progress_item_begin(min, de->d_name, 0);
					if(pgs_progress_item_update(min, 0) == PGS_CANCEL)
					{
						errno = EINTR;
						break;
					}
					pgs_progress_item_end(min);
					if(!min->cfg.dir_filter(de->d_name))
						continue;
					if(lstat(de->d_name, &stat) == 0)
					{
						if(S_ISDIR(stat.st_mode))
							del_delete_directory(min, de->d_name);
						else
							del_delete_file(min, de->d_name);
					}
					else
						break;
				}
				closedir(dir);
			}
			fut_cd(old_dir, NULL, 0);
			if(errno == 0)		/* Don't try to rmdir() again if anything failed above. */
				rmdir(path);
		}
	}
	if(errno)
		err_set(min, errno, CMD_ID, path);

	return (errno == 0) ? TRUE : FALSE;
}

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

/* 1998-09-18 -	A new entrypoint for the delete command. Completely replaces the old one,
**		which has been removed.
*/
int cmd_delete(MainInfo *min, DirPane *src, DirPane *dst, CmdArg *ca)
{
	gchar		old_path[PATH_MAX];
	const gchar	*dest;
	gboolean	ok;
	guint		num = 0;
	mode_t		mode;
	OvwRes		ores;
	GSList		*slist,	 *iter;

	if(!fut_cd(src->dir.path, old_path, sizeof old_path))
		return 0;

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

	ovw_overwrite_begin(min, "Really delete \"%s\"?", 0UL);
	pgs_progress_begin(min, "Delete", PFLG_BUSY_MODE);
	for(iter = slist; !errno && (iter != NULL); iter = g_slist_next(iter))
	{
		dest = dp_full_name(src, DP_SEL_INDEX(src, iter));
		pgs_progress_item_begin(min, dest, 0);
		if(pgs_progress_item_update(min, 0) == PGS_CANCEL)
		{
			errno = EINTR;
			break;
		}
		pgs_progress_item_end(min);
		ores = ovw_overwrite_file(min, dest, NULL);
		if(ores == OVW_SKIP)
			continue;
		else if(ores == OVW_CANCEL)
			break;
		mode = DP_SEL_LSTAT(iter).st_mode;
		if(S_ISDIR(mode))
			ok = del_delete_directory(min, dest);
		else
			ok = del_delete_file(min, dest);
		if(ok && !errno)
		{
			dp_unselect(src, DP_SEL_INDEX(src, iter));
			num++;
		}
		else
			break;
	}
	if(num)
		dp_rescan_dir(src);
	pgs_progress_end(min);
	ovw_overwrite_end(min);

	dp_free_selection(slist);

	fut_cd(old_path, NULL, 0);
	err_show(min);
	return errno == 0;
}
