/*
 * Copyright (C) 2025 The Cbd Developers
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Author: Guido Günther <agx@sigxcpu.org>
 */

#define G_LOG_DOMAIN "cbd-daemon"

#include "cbd-config.h"

#include "cbd-daemon.h"
#include "cbd-manager.h"

#include <glib-unix.h>
#include <gio/gio.h>

/**
 * CbdDaemon:
 *
 * The daemon object
 */


struct _CbdDaemon {
  GApplication       parent;

  CbdManager        *manager;
  CbdChannelManager *channel_manager;
};
G_DEFINE_TYPE (CbdDaemon, cbd_daemon, G_TYPE_APPLICATION)


static gboolean
on_shutdown_signal (gpointer data)
{
  CbdDaemon *self = CBD_DAEMON (data);

  g_debug ("Exiting gracefully.");

  g_application_release (G_APPLICATION (self));

  return FALSE;
}


static gboolean
cbd_daemon_dbus_register (GApplication    *application,
                          GDBusConnection *connection,
                          const gchar     *object_path,
                          GError         **error)
{
  CbdDaemon *self = CBD_DAEMON (application);
  gboolean success;
  g_autoptr (GError) err = NULL;

  success = G_APPLICATION_CLASS (cbd_daemon_parent_class)->dbus_register (application,
                                                                          connection,
                                                                          object_path,
                                                                          error);
  if (!success)
    return success;

  g_debug ("Registered on bus, exporting manager");
  self->manager = cbd_manager_new (self->channel_manager);

  success = g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->manager),
                                              connection,
                                              object_path,
                                              error);
  return success;
}


static void
cbd_daemon_dbus_unregister (GApplication    *application,
                            GDBusConnection *connection,
                            const gchar     *object_path)
{
  CbdDaemon *self = CBD_DAEMON (application);

  g_clear_object (&self->manager);

  G_APPLICATION_CLASS (cbd_daemon_parent_class)->dbus_unregister (application,
                                                                  connection,
                                                                  object_path);
}


static void
cbd_daemon_activate (GApplication *application)
{
  g_application_hold (application);
}


static void
cbd_daemon_dispose (GObject *object)
{
  G_OBJECT_CLASS (cbd_daemon_parent_class)->dispose (object);
}


static void
cbd_daemon_class_init (CbdDaemonClass *klass)
{
  GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->dispose = cbd_daemon_dispose;

  application_class->activate = cbd_daemon_activate;
  application_class->dbus_register = cbd_daemon_dbus_register;
  application_class->dbus_unregister = cbd_daemon_dbus_unregister;
}


static void
cbd_daemon_init (CbdDaemon *self)
{
  self->channel_manager = cbd_channel_manager_new (NULL);

  g_application_set_version (G_APPLICATION (self), CBD_VERSION);

  g_unix_signal_add (SIGTERM, on_shutdown_signal, self);
  g_unix_signal_add (SIGINT, on_shutdown_signal, self);
}


CbdDaemon *
cbd_daemon_new (void)
{
  return g_object_new (CBD_TYPE_DAEMON,
                       "flags", G_APPLICATION_DEFAULT_FLAGS,
                       "application-id", CBD_APP_ID,
                       NULL);
}
