#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gio/gdesktopappinfo.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <libnotify/notify.h>

#include "livepatch-utils.h"
#include "update-notifier.h"

static gboolean
get_ubuntu_advantage_attached(gboolean *attached)
{
    g_autoptr(GError) error = NULL;
    g_autoptr(GDBusConnection) bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
    if (bus == NULL) {
        g_warning ("Failed to get system bus: %s", error->message);
        return FALSE;
    }

    g_autoptr(GVariant) result = g_dbus_connection_call_sync (bus,
        "com.canonical.UbuntuAdvantage",
        "/com/canonical/UbuntuAdvantage/Manager",
        "org.freedesktop.DBus.Properties",
        "Get",
        g_variant_new ("(ss)", "com.canonical.UbuntuAdvantage.Manager", "Attached"),
        G_VARIANT_TYPE ("(v)"),
        G_DBUS_CALL_FLAGS_NONE,
        -1,
        NULL,
        &error);
    if (result == NULL) {
        g_warning ("Failed to contact Ubuntu Advantage D-Bus service: %s", error->message);
        return FALSE;
    }

    g_autoptr(GVariant) value = NULL;
    g_variant_get (result, "(v)", &value);
    if (!g_variant_is_of_type (value, G_VARIANT_TYPE("b"))) {
        g_warning ("Attached property has wrong type");
        return FALSE;
    }
    g_variant_get (value, "b", attached);

    return TRUE;
}

static void
notify_action_cb (NotifyNotification *notification,
                  char *action,
                  gpointer user_data)
{
    if (g_strcmp0 (action, "decline") == 0) {
        // User doesn't want to be notified again.
        g_autoptr(GSettings) settings = g_settings_new (SETTINGS_SCHEMA);
        g_settings_set_boolean (settings, SETTINGS_KEY_NOTIFY_UBUNTU_ADVANTAGE_AVAILABLE, TRUE);
    } else if (g_strcmp0 (action, "enable") == 0) {
        // Open software properties
        g_autoptr(GDesktopAppInfo) info = NULL;
        g_autoptr(GdkAppLaunchContext) context = NULL;
        g_autoptr(GError) error = NULL;

        info = g_desktop_app_info_new (LIVEPATCH_DESKTOP_FILE);
        if (!info) {
            g_warning ("Could not find application '%s'", LIVEPATCH_DESKTOP_FILE);
            return;
        }

        context = gdk_display_get_app_launch_context (gdk_display_get_default ());
        if (!g_app_info_launch (G_APP_INFO (info), NULL, G_APP_LAUNCH_CONTEXT (context), &error)) {
            g_warning ("Could not launch application '%s'", LIVEPATCH_DESKTOP_FILE);
        }
    } else {
        g_warning ("Unknown action: %s", action);
    }
}

static gboolean
show_offer_notification (void)
{
    NotifyNotification *n;
    g_autoptr(GError) error = NULL;

    n = notify_notification_new (_("Ubuntu Pro is available for this computer."),
                                 _("Do you want to enable Ubuntu Pro?"), "distributor-logo");
    notify_notification_set_timeout (n, 60000);

    notify_notification_add_action (n, "decline", _("Don’t remind me again"),
				    notify_action_cb, NULL, NULL);
    notify_notification_add_action (n, "enable", _("Enable Ubuntu Pro"),
				    notify_action_cb, NULL, NULL);

    g_signal_connect (n, "closed", G_CALLBACK (gtk_main_quit), NULL);

    if (!notify_notification_show (n, &error)) {
        g_warning ("Could not show notification: '%s", error->message);
        return FALSE;
    }

    return TRUE;
}

int
main (int argc, char **argv)
{
    gtk_init (&argc, &argv);

    notify_init ("update-notifier");

    setlocale (LC_ALL, "");
    bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    textdomain (GETTEXT_PACKAGE);

    // Check if user has opted out of notification.
    g_autoptr(GSettings) settings = g_settings_new (SETTINGS_SCHEMA);
    if (!g_settings_get_boolean (settings, SETTINGS_KEY_NOTIFY_UBUNTU_ADVANTAGE_AVAILABLE)) {
        return EXIT_SUCCESS;
    }

    // Check if already attached.
    gboolean attached;
    if (!get_ubuntu_advantage_attached (&attached)) {
        return EXIT_FAILURE;
    }
    if (attached) {
        return EXIT_SUCCESS;
    }

    if (show_offer_notification ())
        gtk_main ();

    return EXIT_SUCCESS;
}
