/*
 * Copyright (c) 2012-2025 Daniele Bartolini et al.
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

namespace Crown
{
public class AppChooserButton : Gtk.Box
{
	public const string APP_PREDEFINED = "predefined"; ///< Open with a predefined system application.
	public const string APP_DEFAULT    = "default";    ///< Open with the default application for the file type.
	public const string APP_CUSTOM     = "custom";     ///< Open with a custom application defined by the user.

	// See: https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/gtkappchooserbutton.c
	public enum ModelColumn
	{
		APP_INFO,
		NAME
	}

	public Gtk.EventControllerScroll _controller_scroll;
	public Gtk.AppChooserButton _app_chooser_button;

	public AppChooserButton(string mime_type)
	{
		Object(orientation: Gtk.Orientation.HORIZONTAL);

		_app_chooser_button = new Gtk.AppChooserButton(mime_type);
		_app_chooser_button.append_custom_item(APP_DEFAULT, "Open by extension", null);
		_app_chooser_button.set_active_custom_item(APP_DEFAULT);
#if CROWN_PLATFORM_LINUX
		_app_chooser_button.show_dialog_item = true;
#endif

#if CROWN_GTK3
		_app_chooser_button.scroll_event.connect(() => {
				GLib.Signal.stop_emission_by_name(_app_chooser_button, "scroll-event");
				return Gdk.EVENT_PROPAGATE;
			});
#else
		_controller_scroll = new Gtk.EventControllerScroll(Gtk.EventControllerScrollFlags.BOTH_AXES);
		_controller_scroll.set_propagation_phase(Gtk.PropagationPhase.CAPTURE);
		_controller_scroll.scroll.connect(() => {
				// Do nothing, just consume the event to stop
				// the annoying scroll default behavior.
			});
		_app_chooser_button.add_controller(_controller_scroll);
#endif

		this.pack_start(_app_chooser_button);
	}

	public GLib.AppInfo? get_app_info()
	{
		return _app_chooser_button.get_app_info();
	}

	/// Sets the app to @a app_name. If @a app_name is APP_PREDEFINED, it tries
	/// to set the predefined app based @a app_id.
	public void set_app(string app_name, string? app_id)
	{
		if (app_name != APP_PREDEFINED) {
			_app_chooser_button.set_active_custom_item(app_name);
			return;
		}

		if (app_id == null) {
			_app_chooser_button.set_active_custom_item(APP_DEFAULT);
			return;
		}

		_app_chooser_button.model.foreach((model, path, iter) => {
				Value val;
				model.get_value(iter, ModelColumn.APP_INFO, out val);

				GLib.AppInfo app_info = (GLib.AppInfo)val;
				if (app_info != null && app_info.get_id() == app_id) {
					_app_chooser_button.set_active_iter(iter);
					return true;
				}

				return false;
			});
	}

	/// Returns the item name of the selected application. If the application is predefined,
	/// it returns its @a app_id.
	public string selected_app(out string? app_id)
	{
		app_id = null;

		Gtk.TreeIter iter;
		if (_app_chooser_button.get_active_iter(out iter)) {
			Value val;
			_app_chooser_button.model.get_value(iter, ModelColumn.NAME, out val);
			string name = (string)val;
			if (name != null)
				return name;

			GLib.AppInfo app_info = _app_chooser_button.get_app_info();
			if (app_info != null) {
				app_id = app_info.get_id();
				return AppChooserButton.APP_PREDEFINED;
			}
		}

		return APP_DEFAULT;
	}
}

} /* namespace Crown */
