/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
 *
 * Copyright 2025 GNOME Foundation, Inc.
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 * 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 Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Authors:
 *  - Philip Withnall <pwithnall@gnome.org>
 */

#include "config.h"

#include <glib.h>
#include <gio/gio.h>
#include <libmalcontent-timer/timer-store.h>
#include <locale.h>


static GFile *
create_tmp_store_directory (void)
{
  g_autoptr(GError) local_error = NULL;
  g_autofree char *store_directory_path = NULL;

  store_directory_path = g_dir_make_tmp ("timer-store-test-XXXXXX", &local_error);
  g_assert_no_error (local_error);
  return g_file_new_for_path (store_directory_path);
}

static void
assert_rm_rf (GFile *dir)
{
  g_autoptr(GFileEnumerator) enumerator = NULL;
  g_autoptr(GFileInfo) child_info = NULL;
  g_autoptr(GError) local_error = NULL;

  enumerator = g_file_enumerate_children (dir, "standard::type,standard::name",
                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                          NULL, &local_error);
  g_assert_no_error (local_error);

  while ((child_info = g_file_enumerator_next_file (enumerator, NULL, &local_error)))
    {
      const char *name = g_file_info_get_name (child_info);
      g_autoptr(GFile) child = g_file_get_child (dir, name);

      if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY)
        {
          assert_rm_rf (child);
        }
      else
        {
          g_file_delete (child, NULL, &local_error);
          g_assert_no_error (local_error);
        }

      g_clear_object (&child_info);
    }

  g_file_delete (dir, NULL, &local_error);
  g_assert_no_error (local_error);
}

static void
async_result_cb (GObject      *object,
                 GAsyncResult *result,
                 void         *user_data)
{
  GAsyncResult **result_out = user_data;

  g_assert (*result_out == NULL);
  *result_out = g_object_ref (result);
  g_main_context_wakeup (NULL);
}


static void
test_timer_store_types (void)
{
  g_test_summary ("Test that the GType definitions for various types work");

  g_type_ensure (mct_timer_store_get_type ());
}

static void
test_timer_store_open_no_database (void)
{
  g_autoptr(GFile) store_directory = NULL;
  g_autoptr(MctTimerStore) store = NULL;
  g_autoptr(GAsyncResult) result = NULL;
  const MctTimerStoreTransaction *transaction;
  g_autoptr(GError) local_error = NULL;

  g_test_summary ("Test that opening a database works when no file exists yet");

  /* Try with a directory which exists but contains no files */
  store_directory = create_tmp_store_directory ();
  store = mct_timer_store_new (store_directory);

  mct_timer_store_open_username_async (store, "username", NULL, async_result_cb, &result);
  while (result == NULL)
    g_main_context_iteration (NULL, TRUE);
  transaction = mct_timer_store_open_username_finish (store, result, &local_error);
  g_assert_no_error (local_error);
  g_assert_nonnull (transaction);

  mct_timer_store_roll_back_transaction (store, g_steal_pointer (&transaction));

  /* And again with a directory which doesn’t exist */
  assert_rm_rf (store_directory);
  g_clear_object (&result);

  mct_timer_store_open_username_async (store, "username", NULL, async_result_cb, &result);
  while (result == NULL)
    g_main_context_iteration (NULL, TRUE);
  transaction = mct_timer_store_open_username_finish (store, result, &local_error);
  g_assert_no_error (local_error);
  g_assert_nonnull (transaction);

  mct_timer_store_roll_back_transaction (store, g_steal_pointer (&transaction));
}

int
main (int    argc,
      char **argv)
{
  setlocale (LC_ALL, "");
  g_test_init (&argc, &argv, NULL);

  g_test_add_func ("/timer-store/types", test_timer_store_types);
  g_test_add_func ("/timer-store/open-no-database", test_timer_store_open_no_database);

  return g_test_run ();
}
