/*
 * Copyright (C) 2011 Igalia S.L.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "TestMain.h"

#include <glib/gstdio.h>
#include <wtf/FileSystem.h>

#if PLATFORM(GTK)
#include <gtk/gtk.h>
#endif

bool Test::shouldInitializeWebProcessExtensions = false;

GRefPtr<GDBusServer> Test::s_dbusServer;
Vector<GRefPtr<GDBusConnection>> Test::s_dbusConnections;
HashMap<uint64_t, GDBusConnection*> Test::s_dbusConnectionPageMap;
WebKitMemoryPressureSettings* Test::s_memoryPressureSettings = nullptr;
#if ENABLE(WPE_PLATFORM)
bool Test::s_useWPELegacyAPI = false;
#endif

void beforeAll();
void afterAll();

static GUniquePtr<char> testDataDirectory(g_dir_make_tmp("WebKitGLibTests-XXXXXX", nullptr));

const char* Test::dataDirectory()
{
    return testDataDirectory.get();
}

static void registerGResource(void)
{
    GUniquePtr<char> resourcesPath(g_build_filename(WEBKIT_TEST_RESOURCES_DIR, "webkitglib-tests-resources.gresource", nullptr));
    GResource* resource = g_resource_load(resourcesPath.get(), nullptr);
    g_assert_nonnull(resource);

    g_resources_register(resource);
    g_resource_unref(resource);
}

static void removeNonEmptyDirectory(const char* directoryPath)
{
    GDir* directory = g_dir_open(directoryPath, 0, 0);
    g_assert_nonnull(directory);
    const char* fileName;
    while ((fileName = g_dir_read_name(directory))) {
        GUniquePtr<char> filePath(g_build_filename(directoryPath, fileName, nullptr));
        if (g_file_test(filePath.get(), G_FILE_TEST_IS_DIR))
            removeNonEmptyDirectory(filePath.get());
        else
            g_unlink(filePath.get());
    }
    g_dir_close(directory);
    g_rmdir(directoryPath);
}

static void dbusConnectionClosed(GDBusConnection* connection)
{
    auto index = Test::s_dbusConnections.find(connection);
    g_assert(index != notFound);

    for (auto it : Test::s_dbusConnectionPageMap) {
        if (it.value == connection)
            it.value = nullptr;
    }
    Test::s_dbusConnections.removeAt(index);
}

static gboolean dbusServerConnection(GDBusServer* server, GDBusConnection* connection)
{
    g_signal_connect(connection, "closed", G_CALLBACK(dbusConnectionClosed), nullptr);
    g_assert(!Test::s_dbusConnections.contains(connection));
    Test::s_dbusConnections.append(connection);

    g_dbus_connection_signal_subscribe(connection, nullptr, "org.webkit.gtk.WebProcessExtensionTest", "PageCreated", "/org/webkit/gtk/WebProcessExtensionTest",
        nullptr, G_DBUS_SIGNAL_FLAGS_NONE, [](GDBusConnection* connection, const char*, const char*, const char*, const char*, GVariant* parameters, gpointer) {
            guint64 pageID;
            g_variant_get(parameters, "(t)", &pageID);
            g_assert(Test::s_dbusConnections.contains(connection));
            Test::s_dbusConnectionPageMap.set(pageID, connection);
        }, nullptr, nullptr);

    return TRUE;
}

static void startDBusServer()
{
    GUniqueOutPtr<GError> error;
    GUniquePtr<char> address(g_strdup_printf("unix:tmpdir=%s", testDataDirectory.get()));
    GUniquePtr<char> guid(g_dbus_generate_guid());
    Test::s_dbusServer = adoptGRef(g_dbus_server_new_sync(address.get(), G_DBUS_SERVER_FLAGS_NONE, guid.get(), nullptr, nullptr, &error.outPtr()));
    if (!Test::s_dbusServer)
        g_error("Failed to start DBus server: %s", error->message);

    g_signal_connect(Test::s_dbusServer.get(), "new-connection", G_CALLBACK(dbusServerConnection), nullptr);
    g_dbus_server_start(Test::s_dbusServer.get());
}

static void stopDBusServer()
{
    g_dbus_server_stop(Test::s_dbusServer.get());
    Test::s_dbusServer = nullptr;
}

#if ENABLE(WPE_PLATFORM)
static void parseWPEArgs(int argc, char** argv)
{
    for (int i = 1; i < argc; ++i) {
        if (!g_strcmp0(argv[i], "--wpe-legacy-api"))
            Test::s_useWPELegacyAPI = true;
    }
}
#endif

int main(int argc, char** argv)
{
    g_unsetenv("DBUS_SESSION_BUS_ADDRESS");
#if PLATFORM(GTK)
    gtk_test_init(&argc, &argv, nullptr);
#else
    g_test_init(&argc, &argv, nullptr);
#endif
#if ENABLE(WPE_PLATFORM)
    parseWPEArgs(argc, argv);
#endif

    g_set_prgname(FileSystem::currentExecutableName().data());
    g_setenv("WEBKIT_EXEC_PATH", WEBKIT_EXEC_PATH, FALSE);
    g_setenv("WEBKIT_INJECTED_BUNDLE_PATH", WEBKIT_INJECTED_BUNDLE_PATH, FALSE);
    g_setenv("WEBKIT_INSPECTOR_RESOURCES_PATH", WEBKIT_INSPECTOR_RESOURCES_PATH, FALSE);
    // Sandbox requires using GApplication.
    g_setenv("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS", "1", TRUE);
    g_setenv("LC_ALL", "C", TRUE);
    g_setenv("GIO_USE_VFS", "local", TRUE);
    g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
    // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
    g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
    g_setenv("TZ", "America/Los_Angeles", TRUE);
#if PLATFORM(WPE)
    g_setenv("WPE_PLATFORMS_PATH", WPE_MOCK_PLATFORM_DIR, TRUE);
#endif
    g_test_bug_base("https://bugs.webkit.org/");

    registerGResource();
    startDBusServer();

    beforeAll();
    int returnValue = g_test_run();
    afterAll();

    stopDBusServer();
    removeNonEmptyDirectory(testDataDirectory.get());

    return returnValue;
}

