/* plugin-host-sdk-provider.c
 *
 * Copyright 2024 Christian Hergert <chergert@redhat.com>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */

#include "config.h"

#include "foundry-util-private.h"

#include "plugin-host-sdk.h"
#include "plugin-host-sdk-provider.h"

struct _PluginHostSdkProvider
{
  FoundrySdkProvider  parent_instance;
  FoundrySdk         *sdk;
  char               *systemd_run_path;
};

G_DEFINE_FINAL_TYPE (PluginHostSdkProvider, plugin_host_sdk_provider, FOUNDRY_TYPE_SDK_PROVIDER)

static DexFuture *
plugin_host_sdk_provider_load_fiber (gpointer data)
{
  PluginHostSdkProvider *self = data;
  g_autoptr(FoundryContext) context = NULL;
  g_autoptr(GError) error = NULL;
  static const char *systemd_run_paths[] = {
    "/usr/bin/systemd-run",
    "/bin/systemd-run",
  };

  g_assert (PLUGIN_IS_HOST_SDK_PROVIDER (self));

  if (!(context = foundry_contextual_acquire (FOUNDRY_CONTEXTUAL (self), &error)))
    return dex_future_new_for_error (g_steal_pointer (&error));

  for (guint i = 0; i < G_N_ELEMENTS (systemd_run_paths); i++)
    {
      g_autoptr(GFile) file = NULL;
      g_autofree char *path = NULL;

      if (_foundry_in_container ())
        path = g_build_filename ("/var/run/host", systemd_run_paths[i], NULL);
      else
        path = g_strdup (systemd_run_paths[i]);

      file = g_file_new_for_path (path);

      if (dex_await_boolean (dex_file_query_exists (file), NULL))
        {
          g_set_str (&self->systemd_run_path, systemd_run_paths[i]);
          break;
        }
    }

  if (self->systemd_run_path)
    g_debug ("Found `systemd-run` at `%s`", self->systemd_run_path);
  else
    g_debug ("`systemd-run` could not be found on host");

  self->sdk = plugin_host_sdk_new (context, self->systemd_run_path);
  foundry_sdk_provider_sdk_added (FOUNDRY_SDK_PROVIDER (self), self->sdk);

  return dex_future_new_true ();
}

static DexFuture *
plugin_host_sdk_provider_load (FoundrySdkProvider *provider)
{
  PluginHostSdkProvider *self = (PluginHostSdkProvider *)provider;

  FOUNDRY_ENTRY;

  g_assert (FOUNDRY_IS_MAIN_THREAD ());
  g_assert (PLUGIN_IS_HOST_SDK_PROVIDER (self));

  FOUNDRY_RETURN (dex_scheduler_spawn (dex_scheduler_get_default (), 0,
                                        plugin_host_sdk_provider_load_fiber,
                                        g_object_ref (self),
                                        g_object_unref));
}

static DexFuture *
plugin_host_sdk_provider_unload (FoundrySdkProvider *provider)
{
  PluginHostSdkProvider *self = (PluginHostSdkProvider *)provider;
  g_autoptr(FoundryContext) context = NULL;

  FOUNDRY_ENTRY;

  g_assert (FOUNDRY_IS_MAIN_THREAD ());
  g_assert (PLUGIN_IS_HOST_SDK_PROVIDER (self));

  if (self->sdk != NULL)
    {
      foundry_sdk_provider_sdk_removed (FOUNDRY_SDK_PROVIDER (self), self->sdk);
      g_clear_object (&self->sdk);
    }

  FOUNDRY_RETURN (dex_future_new_true ());
}

static void
plugin_host_sdk_provider_finalize (GObject *object)
{
  PluginHostSdkProvider *self = (PluginHostSdkProvider *)object;

  g_clear_object (&self->sdk);
  g_clear_pointer (&self->systemd_run_path, g_free);

  G_OBJECT_CLASS (plugin_host_sdk_provider_parent_class)->finalize (object);
}

static void
plugin_host_sdk_provider_class_init (PluginHostSdkProviderClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  FoundrySdkProviderClass *sdk_provider_class = FOUNDRY_SDK_PROVIDER_CLASS (klass);

  object_class->finalize = plugin_host_sdk_provider_finalize;

  sdk_provider_class->load = plugin_host_sdk_provider_load;
  sdk_provider_class->unload = plugin_host_sdk_provider_unload;
}

static void
plugin_host_sdk_provider_init (PluginHostSdkProvider *self)
{
}
