// This file is part of GNOME Boxes. License: LGPLv2+
using Gtk;

private class Boxes.Notificationbar: Gtk.Grid {
    public const int DEFAULT_TIMEOUT = 6;
    private const int MAX_NOTIFICATIONS = 5;

    GLib.List<Widget> active_notifications;

    public Searchbar searchbar;

    construct {
        orientation = Gtk.Orientation.VERTICAL;
        valign = Gtk.Align.START;
        halign = Gtk.Align.CENTER;
        get_style_context ().add_class ("transparent-bg");

        show ();

        active_notifications = new GLib.List<Widget> ();

        App.app.notify["page"].connect ( () => {
            foreach (var w in active_notifications) {
                var parent = w.get_parent () as Container;
                if (parent != null)
                    parent.remove (w);
                add_notification (w);
            }
        });
    }

    public Boxes.Notification display_for_action (string                          message,
                                                  string                          action_label,
                                                  owned Notification.OKFunc       action_func,
                                                  owned Notification.DismissFunc? ignore_func = null,
                                                  int                             timeout = DEFAULT_TIMEOUT) {
        return display (message, MessageType.INFO, action_label, (owned) action_func, (owned) ignore_func, timeout);
    }

    public Boxes.Notification display_for_optional_auth (string                           broker_name,
                                                         owned AuthNotification.AuthFunc? auth_func,
                                                         owned Notification.DismissFunc?  dismiss_func) {
        Notification.OKFunc next_auth_step = () => {
            var auth_string = "<span font-weight=\"bold\">" + _("Sign In to %s").printf(broker_name) + "</span>";
            display_for_auth (auth_string, (owned) auth_func, (owned) dismiss_func);
        };
        return display_for_action (_("Not connected to %s").printf (broker_name),
                                   _("Sign In"),
                                   (owned) next_auth_step,
                                   (owned) dismiss_func, -1);
    }

    public Boxes.AuthNotification display_for_auth (string                           auth_string,
                                                    owned AuthNotification.AuthFunc? auth_func,
                                                    owned Notification.DismissFunc?  dismiss_func,
                                                    bool                             need_username = true) {
        var notification = new Boxes.AuthNotification (auth_string,
                                                       (owned) auth_func,
                                                       (owned) dismiss_func,
                                                       need_username,
                                                       searchbar);

        active_notifications.prepend (notification);

        notification.dismissed.connect ( () => {
            active_notifications.remove (notification);
        });

        add_notification (notification);

        return notification;
    }

    public Boxes.Notification display_error (string message, int timeout = DEFAULT_TIMEOUT) {
        return display (message, MessageType.ERROR, null, null, null, timeout);
    }

    public void dismiss_all () {
        foreach (var notification in active_notifications)
            (notification as Notification).dismiss ();
    }

    private void add_notification (Widget w) {
        add (w);
    }

    private Boxes.Notification display (string                          message,
                                        MessageType                     message_type,
                                        string?                         ok_label,
                                        owned Notification.OKFunc?      ok_func,
                                        owned Notification.DismissFunc? dismiss_func,
                                        int                             timeout) {
        var notification = new Boxes.Notification (message,
                                                   message_type,
                                                   ok_label,
                                                   (owned) ok_func,
                                                   (owned) dismiss_func,
                                                   timeout);

        var excess_notifications = (int) active_notifications.length () - MAX_NOTIFICATIONS + 1;

        for (var i = excess_notifications; i > 0; i--) {
            var last_notification = active_notifications.nth_data (active_notifications.length () - i)
                                    as Boxes.Notification;

            last_notification.dismiss ();
        }

        active_notifications.prepend (notification);

        notification.dismissed.connect ( () => {
            active_notifications.remove (notification);
        });

        add_notification (notification);

        return notification;
    }
}
