/*
 * Copyright (C) 2019 Purism SPC
 * SPDX-License-Identifier: LGPL-2.1+
 * Author: Guido Günther <agx@sigxcpu.org>
 */
#include "gth-names.h"
#include "gth-manager.h"

#include "gth-cooling-device.h"
#include "gth-thermal-zone.h"
/**
 * SECTION:gth-manager
 * @short_description: The Manager object
 * @Title: GthManager
 *
 * This object is also a GDBusObjectManagerClient, and therefore it
 * allows to use the standard ObjectManager interface to list and
 * handle the #GthCoolingDevice and #GthTermalZone objects.
 */

typedef struct _GthManager {
  GthGdbusObjectManagerClient parent;

} GthManager;

G_DEFINE_TYPE (GthManager, gth_manager, GTH_GDBUS_TYPE_OBJECT_MANAGER_CLIENT);


static GType
get_proxy_type (GDBusObjectManagerClient *manager G_GNUC_UNUSED,
		const gchar *object_path G_GNUC_UNUSED,
		const gchar *interface_name, gpointer user_data G_GNUC_UNUSED)
{
  static gsize once_init_value = 0;
  static GHashTable *lookup_hash;
  GType ret;

  if (interface_name == NULL)
    return GTH_GDBUS_TYPE_OBJECT_PROXY;
  if (g_once_init_enter (&once_init_value))
    {
      lookup_hash = g_hash_table_new (g_str_hash, g_str_equal);
      g_hash_table_insert (lookup_hash, (gpointer) "org.sigxcpu.Thermal.CoolingDevice", GSIZE_TO_POINTER (GTH_TYPE_COOLING_DEVICE));
      g_hash_table_insert (lookup_hash, (gpointer) "org.sigxcpu.Thermal.ThermalZone", GSIZE_TO_POINTER (GTH_TYPE_THERMAL_ZONE));
      g_once_init_leave (&once_init_value, 1);
    }
  ret = (GType) GPOINTER_TO_SIZE (g_hash_table_lookup (lookup_hash, interface_name));
  if (ret == (GType) 0)
    ret = G_TYPE_DBUS_PROXY;
  return ret;
}



static GPtrArray *
get_by_iface (GthManager *self, const char *iface_name)
{
  GPtrArray *ret;
  GList *objs, *l;
  
  objs = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self));
  ret = g_ptr_array_new ();
    
  for (l = objs; l; l = g_list_next (l)) {
    GDBusObject *obj;
    GDBusInterface *iface = NULL;

    obj = G_DBUS_OBJECT (l->data);
    iface = g_dbus_object_get_interface (obj, iface_name);
    if (iface)
      g_ptr_array_add (ret, iface);
  }

  g_list_free_full (objs, g_object_unref);
  return ret;
}


static void
gth_manager_class_init (GthManagerClass *klass)
{
}

static void
gth_manager_init (GthManager *self)
{
}

/**
 * gth_manager_new_sync:
 * @connection: A #GDBusConnection.
 * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.
 * @cancellable: (allow-none): A #GCancellable or %NULL.
 * @error: Return location for error or %NULL
 *
 * Synchronously creates a #GthManager.
 *
 * The calling thread is blocked until a reply is received.
 *
 * See gthcli_manager_new() for the asynchronous version of this constructor.
 *
 * Returns: (transfer full) (type GthManager): The constructed object
 * manager client or %NULL if @error is set.
 */
GthManager *
gth_manager_new_sync (GDBusConnection                *connection,
		      GDBusObjectManagerClientFlags   flags,
		      GCancellable                   *cancellable,
		      GError                        **error)
{
  return GTH_MANAGER (g_initable_new (GTH_TYPE_MANAGER,
				      cancellable,
				      error,
				      "name", GTH_DBUS_NAME,
				      "object-path", GTH_DBUS_PATH,
				      "flags", flags,
				      "connection", connection,
				      "get-proxy-type-func", get_proxy_type,
				      NULL));
}

/**
 * gth_manager_get_cooling_devices:
 * @self: A #GthManager
 * 
 * Get the known cooling devices
 *
 * Returns: (transfer full) (nullable) (element-type GthCoolingDevice): the cooling devices
 */
GPtrArray *
gth_manager_get_cooling_devices (GthManager *self)
{
  g_return_val_if_fail (GTH_IS_MANAGER(self), NULL);

  return get_by_iface (self, GTH_DBUS_IFACE_COOLING_DEVICE);
}


/**
 * gth_manager_get_thermal_zones:
 * @self: A #GthManager
 * 
 * Get the known thermal zones
 *
 * Returns: (transfer full) (nullable) (element-type GthThermalZone): the thermal zones
 */
GPtrArray *
gth_manager_get_thermal_zones (GthManager *self)
{
  g_return_val_if_fail (GTH_IS_MANAGER(self), NULL);

  return get_by_iface (self, GTH_DBUS_IFACE_THERMAL_ZONE);
}

