/* SPDX-FileCopyrightText: 2005 - Paolo Borelli
 * SPDX-FileCopyrightText: 2025 - Sébastien Wilmet
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#include "tepl-statusbar.h"
#include "tepl-utils.h"

/**
 * SECTION:statusbar
 * @Title: TeplStatusbar
 * @Short_description: Subclass of #GtkStatusbar
 *
 * #TeplStatusbar is a subclass of #GtkStatusbar with additional features.
 *
 * The tepl_utils_setup_statusbar() function is already called.
 */

struct _TeplStatusbarPrivate
{
	guint generic_message_context_id;

	/* Flash timeout data */
	guint flash_timeout_id;
	guint flash_context_id;
	guint flash_message_id;
};

G_DEFINE_TYPE_WITH_PRIVATE (TeplStatusbar, tepl_statusbar, GTK_TYPE_STATUSBAR)

static void
tepl_statusbar_dispose (GObject *object)
{
	TeplStatusbar *statusbar = TEPL_STATUSBAR (object);

	g_clear_handle_id (&statusbar->priv->flash_timeout_id, g_source_remove);

	G_OBJECT_CLASS (tepl_statusbar_parent_class)->dispose (object);
}

static void
tepl_statusbar_class_init (TeplStatusbarClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);

	object_class->dispose = tepl_statusbar_dispose;
}

static void
tepl_statusbar_init (TeplStatusbar *statusbar)
{
	statusbar->priv = tepl_statusbar_get_instance_private (statusbar);

	statusbar->priv->generic_message_context_id =
		gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "generic_message");

	tepl_utils_setup_statusbar (GTK_STATUSBAR (statusbar));
	gtk_widget_set_hexpand (GTK_WIDGET (statusbar), TRUE);
}

/**
 * tepl_statusbar_new:
 *
 * Returns: (transfer floating): a new #TeplStatusbar.
 * Since: 6.14
 */
TeplStatusbar *
tepl_statusbar_new (void)
{
	return g_object_new (TEPL_TYPE_STATUSBAR, NULL);
}

static gboolean
flash_timeout_cb (gpointer user_data)
{
	TeplStatusbar *statusbar = TEPL_STATUSBAR (user_data);

	gtk_statusbar_remove (GTK_STATUSBAR (statusbar),
			      statusbar->priv->flash_context_id,
			      statusbar->priv->flash_message_id);

	statusbar->priv->flash_timeout_id = 0;
	return G_SOURCE_REMOVE;
}

/**
 * tepl_statusbar_flash_message:
 * @statusbar: a #TeplStatusbar.
 * @context_id: a context ID obtained with gtk_statusbar_get_context_id().
 * @msg: the message.
 *
 * Flashes a temporary message on the statusbar.
 *
 * The message is displayed during a short amount of time and then disappears
 * automatically.
 *
 * Since: 6.14
 */
void
tepl_statusbar_flash_message (TeplStatusbar *statusbar,
			      guint          context_id,
			      const gchar   *msg)
{
	g_return_if_fail (TEPL_IS_STATUSBAR (statusbar));
	g_return_if_fail (msg != NULL);

	/* Remove a currently ongoing flash message. */
	if (statusbar->priv->flash_timeout_id > 0)
	{
		g_source_remove (statusbar->priv->flash_timeout_id);
		statusbar->priv->flash_timeout_id = 0;

		gtk_statusbar_remove (GTK_STATUSBAR (statusbar),
				      statusbar->priv->flash_context_id,
				      statusbar->priv->flash_message_id);
	}

	statusbar->priv->flash_context_id = context_id;
	statusbar->priv->flash_message_id = gtk_statusbar_push (GTK_STATUSBAR (statusbar),
								context_id,
								msg);

	/* Flash duration: 3 seconds.
	 * g_timeout_add_seconds() is not used to ensure a good precision.
	 */
	statusbar->priv->flash_timeout_id = g_timeout_add (3000, flash_timeout_cb, statusbar);
}

/**
 * tepl_statusbar_flash_generic_message:
 * @statusbar: a #TeplStatusbar.
 * @msg: the message.
 *
 * Like tepl_statusbar_flash_message() but using a generic @context_id.
 *
 * If you need to call gtk_statusbar_remove_all() or gtk_statusbar_pop(), then
 * use tepl_statusbar_flash_message() instead. Otherwise using this function is
 * sufficient.
 *
 * Since: 6.14
 */
void
tepl_statusbar_flash_generic_message (TeplStatusbar *statusbar,
				      const gchar   *msg)
{
	g_return_if_fail (TEPL_IS_STATUSBAR (statusbar));
	g_return_if_fail (msg != NULL);

	tepl_statusbar_flash_message (statusbar,
				      statusbar->priv->generic_message_context_id,
				      msg);
}
