// vim: colorcolumn=80 ts=4 sw=4

#include "progress-page.h"

static GtkWidget *progress_box;
static GtkWidget *progress_text;
static GtkWidget *progress_bar;
static GtkWidget *progress_heading;
static GtkWidget *progress_percent_label;
static GtkWidget *spinner;

/* This is kind of lame, but it's to work around the fact that the
 * FlatpakTransaction 'changed' signal doesn't seem to be a thing for
 * removal and upgrade operations, so we don't get to display a nice progress
 * bar.
 */
static void
swap_progress_bar_for_spinner (void)
{
	gtk_widget_set_visible (progress_bar, FALSE);
	gtk_widget_set_visible (spinner, TRUE);
	gtk_spinner_start (GTK_SPINNER(spinner));
}

static void
new_transaction_cb (GfiProgress *progress,
		GfiProgressTransactionType transaction_type,
		gpointer user_data)
{
	GfiProgressActionType action_type;
	const char *transaction_name;
	g_autofree char *tmp = NULL;

	action_type = gfi_progress_get_action_type (progress);
	transaction_name = gfi_progress_get_transaction_name (progress);

	if (! transaction_name)
	{
		tmp = g_strdup ("Please Wait...");
		goto done;
	}

	switch (action_type)
	{
		case GFI_PROGRESS_ACTION_TYPE_INSTALL:
			if (transaction_type == GFI_PROGRESS_TRANSACTION_TYPE_APP) {
				tmp = g_strdup_printf ("Installing application:  %s",
						transaction_name);
			}
			else if (transaction_type == GFI_PROGRESS_TRANSACTION_TYPE_DEP) {
				tmp = g_strdup_printf ("Installing dependency:  %s",
						transaction_name);
			}
			else {
				tmp = g_strdup_printf ("Installing:  %s",
						transaction_name);
			}
			break;

		case GFI_PROGRESS_ACTION_TYPE_REMOVE:
			swap_progress_bar_for_spinner ();

			if (transaction_type == GFI_PROGRESS_TRANSACTION_TYPE_APP) {
				tmp = g_strdup_printf ("Removing application:  %s",
						transaction_name);
			}
			else if (transaction_type == GFI_PROGRESS_TRANSACTION_TYPE_DEP) {
				tmp = g_strdup_printf ("Removing dependency:  %s",
						transaction_name);
			}
			else {
				tmp = g_strdup_printf ("Removing:  %s",
						transaction_name);
			}
			break;

		case GFI_PROGRESS_ACTION_TYPE_UPGRADE:
			swap_progress_bar_for_spinner ();

			if (transaction_type == GFI_PROGRESS_TRANSACTION_TYPE_APP) {
				tmp = g_strdup_printf ("Upgrading application:  %s",
						transaction_name);
			}
			else if (transaction_type == GFI_PROGRESS_TRANSACTION_TYPE_DEP) {
				tmp = g_strdup_printf ("Upgrading dependency:  %s",
						transaction_name);
			}
			else {
				tmp = g_strdup_printf ("Upgrading:  %s",
						transaction_name);
			}
			break;

		default:
			g_error ("%s: Programmer error: GfiProgressActionType has not "
					"been set. This should not happen. Abort.", __func__);
			break;
	}

done:
	set_heading_text (GTK_LABEL(progress_heading), tmp);
}

static void
update_status_cb (GfiProgress *progress, gpointer user_data)
{
	const char *status = gfi_progress_get_status (progress);

	gtk_label_set_text (GTK_LABEL(progress_text), status);
}

static void
update_progress_cb (GfiProgress *progress, int percent, gpointer user_data)
{
	double fraction;
	g_autofree char *percent_blurb;

	g_return_if_fail (percent >= 0 && percent <= 100);

	fraction = percent / 100.0;
	gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar), fraction);

	percent_blurb = g_strdup_printf ("%d%% Complete", percent);
	gtk_label_set_text (GTK_LABEL(progress_percent_label), percent_blurb);
}

static void
setup_signals (GfiProgress *progress)
{
	/* GfiProgress: */
	g_signal_connect (progress, "update-status",
			G_CALLBACK(update_status_cb), NULL);
	g_signal_connect (progress, "update-progress",
			G_CALLBACK(update_progress_cb), NULL);
	g_signal_connect (progress, "new-transaction",
			G_CALLBACK(new_transaction_cb), NULL);
}

void
setup_progress_page (GtkBuilder *builder, GfiProgress *progress)
{
	GET_WIDGET (builder, progress_box);
	GET_WIDGET (builder, progress_text);
	GET_WIDGET (builder, progress_bar);
	GET_WIDGET (builder, progress_heading);
	GET_WIDGET (builder, progress_percent_label);
	GET_WIDGET (builder, spinner);

	setup_signals (progress);
}
