/*
 * Copyright (C) 2019 Purism SPC
 * SPDX-License-Identifier: GPL-3.0+
 * Author: Guido Günther <agx@sigxcpu.org>
 */

#define G_LOG_DOMAIN "gthd"

#include "gthd.h"
#include "gthd-data.h"
#include "gthd-cooling-device.h"
#include "gthd-thermal-zone.h"
#include "gth-gdbus.h"
#include "gth-names.h"

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


static GMainLoop *loop;
GDBusObjectManagerServer *object_manager;


GQuark gthd_error_quark(void)
{
    static GQuark quark = 0;

    if (!quark)
        quark = g_quark_from_static_string("gthd");

    return quark;
}


static gboolean
quit_cb (gpointer user_data)
{
    g_info ("Caught signal, shutting down...");

    if (loop)
      g_idle_add ((GSourceFunc) g_main_loop_quit, loop);
    else
      exit (0);

    return FALSE;
}


static void
bus_acquired_cb (GDBusConnection *connection,
                 const gchar *name,
                 gpointer user_data)
{
  GthdData *data;
  const GPtrArray *tzones;
  const GPtrArray *cdevs;
  int i;

  g_debug ("Bus acquired, creating manager...");

  /* Create Manager object */
  g_assert (!object_manager);
  object_manager = g_dbus_object_manager_server_new (GTH_DBUS_PATH);

  if (!object_manager) {
    g_warning ("Could not create manager");
    g_main_loop_quit (loop);
    return;
  }

  data = gthd_data_get_default ();
  tzones = gthd_data_get_thermal_zones (data);

  for (i = 0; i < tzones->len; i++) {
    GthdThermalZone *tzone = g_ptr_array_index(tzones, i);
    g_autofree gchar *path = gthd_thermal_zone_get_dbus_path (tzone);
    g_autoptr(GthGdbusObjectSkeleton) obj = gth_gdbus_object_skeleton_new (path);

    g_dbus_object_manager_server_export (object_manager,
					 G_DBUS_OBJECT_SKELETON(obj));
    g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON(obj),
					  G_DBUS_INTERFACE_SKELETON (tzone));
  }

  cdevs = gthd_data_get_cooling_devs (data);
  for (i = 0; i < cdevs->len; i++) {
    GthdCoolingDevice *cdev = g_ptr_array_index(cdevs, i);
    g_autofree gchar *path = gthd_cooling_device_get_dbus_path (cdev);
    g_autoptr(GthGdbusObjectSkeleton) obj = gth_gdbus_object_skeleton_new (path);

    g_dbus_object_manager_server_export (object_manager,
					 G_DBUS_OBJECT_SKELETON(obj));
    g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON(obj),
					  G_DBUS_INTERFACE_SKELETON (cdev));
  }
}


static void
name_acquired_cb (GDBusConnection *connection,
                  const gchar *name,
                  gpointer user_data)
{
  g_debug ("Service name '%s' was acquired", name);

  g_assert (object_manager);
  g_dbus_object_manager_server_set_connection(object_manager, connection);
}

static void
name_lost_cb (GDBusConnection *connection,
              const gchar *name,
              gpointer user_data)
{
  /* Note that we're not allowing replacement, so once the name acquired, the
   * process won't lose it. */
  if (!name)
    g_warning ("Could not get the system bus. Make sure "
	       "the message bus daemon is running!");
  else
    g_warning ("Could not acquire the '%s' service name", name);

  g_main_loop_quit (loop);
}


int main(void)
{
  g_unix_signal_add (SIGTERM, quit_cb, NULL);
  g_unix_signal_add (SIGINT, quit_cb, NULL);

  loop = g_main_loop_new (NULL, FALSE);

  g_bus_own_name (GTH_DBUS_TYPE,
                  GTH_DBUS_NAME,
                  G_BUS_NAME_OWNER_FLAGS_NONE,
                  bus_acquired_cb,
                  name_acquired_cb,
                  name_lost_cb,
                  NULL,
                  NULL);

  g_main_loop_run (loop);
  g_main_loop_unref (loop);
  g_object_unref (gthd_data_get_default());
}
