/*
** 1998-09-17 -	A module to deal with the (possible) overwriting of files, and warn the user
**		when that is about to happen. Deleting a file is considered to be an overwrite.
**		Changing protection bits and owner info is not.
** 1999-03-13 -	Changes for the new dialog module.
*/

#include "gentoo.h"
#include "dialog.h"
#include "strutil.h"
#include "fileutil.h"
#include "overwrite.h"

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

static struct {
	guint		level;
	gboolean	do_all;		/* Gets set when user clicks "All". */
	MainInfo	*min;
	const gchar	*fmt;
	guint32		flags;
	GtkWidget	*label;
	Dialog		*dlg;
} ovw_info = { 0U };		/* Makes sure <level> is 0 on first call. */

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

/* 1998-09-17 -	Begin a "session" with overwrite protection. The <fmt> string is used in a
**		call to sprintf() with the destination file as argument if we need to inform
**		the user. Very handy. Calls to this function REALLY should nest with calls to
**		ovw_overwrite_end()! Or else.
*/
void ovw_overwrite_begin(MainInfo *min, const gchar *fmt, guint32 flags)
{
	if(ovw_info.level == 0)
	{
		ovw_info.do_all = FALSE;
		ovw_info.min = min;
		ovw_info.fmt = fmt;
		ovw_info.flags = flags;
		ovw_info.label = gtk_label_new("");
		ovw_info.dlg = dlg_dialog_hidden(ovw_info.label, "Please Confirm", "OK|All|Skip|Cancel", NULL, NULL);
		dlg_dialog_set_keep(ovw_info.dlg, TRUE);
	}
	else
		fprintf(stderr, "OVERWRITE: Mismatched call (level=%d)!\n", ovw_info.level);
	ovw_info.level++;
}

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

/* 1998-12-20 -	Get a date for file described by <st>, to be shown in dialog, as a struct tm.
**		Currently simply returns the "changed"-time, since I feel it's maybe the most
**		useful.
*/
static struct tm * get_date(struct stat *st)
{
	return localtime(&st->st_ctime);
}

static void get_info(MainInfo *min, gchar *buf, gsize buf_size, const gchar *old_file, const gchar *new_file)
{
	gchar		o_date[64], n_date[64];
	struct stat	o_st, n_st;

	if((stat(old_file, &o_st) == 0) && (stat(new_file, &n_st) == 0))
	{
		strftime(o_date, sizeof o_date, (const char *) min->cfg.opt_overwrite.datefmt, get_date(&o_st));
		strftime(n_date, sizeof n_date, (const char *) min->cfg.opt_overwrite.datefmt, get_date(&n_st));
		g_snprintf(buf, (gulong) buf_size, "\nOld: %u bytes, changed on %s.\n"
						   "New: %u bytes, changed on %s.",
						   (guint) o_st.st_size, o_date,
						   (guint) n_st.st_size, n_date);
	}
}

/* 1998-09-17 -	Inform the overwrite system that the file whose complete (absolute) name is
**		in <file> is about to be modified in a way considered dangerous by the code
**		doing it. Return values:
**		OVW_SKIP	Skip this file, but continue with the overall operation.
**		OVW_PROCEED	Perform operation on this file, then go on to the next.
**		OVW_CANCEL	Abort the entire operation.
** 1998-12-20 -	Added argument <new_file>, which gives the name of the file with which we are
**		about to overwrite <old_file>, when possible. In other cases, it's NULL.
*/
OvwRes ovw_overwrite_file(MainInfo *min, const gchar *old_file, const gchar *new_file)
{
	gchar	buf[PATH_MAX + 2048];
	guint	dlg_res, len;

	if(ovw_info.level)
	{
		if(ovw_info.do_all)		/* Already answered "All"? */
			return OVW_PROCEED;

		if(fut_exists(old_file))
		{
			len = g_snprintf(buf, sizeof buf, ovw_info.fmt, old_file);
			if(new_file != NULL && min->cfg.opt_overwrite.show_info)
				get_info(min, buf + len, sizeof buf - len - 1, old_file, new_file);
			gtk_label_set_text(GTK_LABEL(ovw_info.label), buf);
			dlg_res = dlg_dialog_wait(ovw_info.dlg);
			if(ovw_info.flags & OVWF_HIDE)
				dlg_dialog_hide(ovw_info.dlg);
			switch(dlg_res)
			{
				case 0:		/* OK? */
					return OVW_PROCEED;
				case 1:		/* All? */
					ovw_info.do_all = TRUE;
					if(!(ovw_info.flags & OVWF_HIDE))
						dlg_dialog_hide(ovw_info.dlg);
					return OVW_PROCEED;
				case 2:		/* Skip? */
					return OVW_SKIP;
				default:
					return OVW_CANCEL;
			}
		}
		return OVW_PROCEED;
	}
	return OVW_CANCEL;
}

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

void ovw_overwrite_end(MainInfo *min)
{
	if(--ovw_info.level == 0)
	{
		ovw_info.min = NULL;
		ovw_info.fmt = NULL;
		dlg_dialog_destroy(ovw_info.dlg);
		ovw_info.dlg = NULL;
	}
}
