/*
 * Copyright (C) 2025 Igalia S.L.
 *
 * 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
 * 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 "WebKitTestServer.h"
#include "WebViewTest.h"
#include <wtf/text/MakeString.h>

static WebKitTestServer* kHttpsServer = nullptr;

static const char indexHTML[] =
"<html><body>"
"<input id='enterXR' type=\"button\" value=\"click to enter experience\"/>"
"<script>"
"document.getElementById('enterXR').addEventListener('click', () => {"
"  navigator.xr.requestSession('immersive-vr').then(session => {"
"    console.log('XR session started');"
"    session.addEventListener('end', (event) => {"
"        console.log('XR session ended');"
"    });"
"  }).catch(err => console.error(`XR session failed to start: ${err}`));"
"});"
"</script></body></html>";

static WebKitFeature* findFeature(WebKitFeatureList *featureList, const char *identifier)
{
    for (gsize i = 0; i < webkit_feature_list_get_length(featureList); i++) {
        WebKitFeature* feature = webkit_feature_list_get(featureList, i);
        if (!g_ascii_strcasecmp(identifier, webkit_feature_get_identifier(feature)))
            return feature;
    }
    return nullptr;
}

static void relaxDMABufRequirement(WebKitSettings* settings)
{
    g_autoptr(WebKitFeatureList) featureList = webkit_settings_get_development_features();
    WebKitFeature* feature = findFeature(featureList, "OpenXRDMABufRelaxedForTesting");
    g_assert_nonnull(feature);
    webkit_settings_set_feature_enabled(settings, feature, true);
}

class WebXRTest : public WebViewTest {
public:
    MAKE_GLIB_TEST_FIXTURE(WebXRTest);
    WebXRTest();
    virtual ~WebXRTest() = default;

    static void isImmersiveModeEnabledChanged(GObject*, GParamSpec*, WebXRTest* test)
    {
        g_signal_handlers_disconnect_by_func(test->webView(), reinterpret_cast<void*>(isImmersiveModeEnabledChanged), test);
        g_main_loop_quit(test->m_mainLoop);
    }

    static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest *request, WebXRTest* test)
    {
        g_assert_true(WEBKIT_IS_XR_PERMISSION_REQUEST(request));
        g_assert_true(test->m_isExpectingPermissionRequest);

        webkit_permission_request_allow(request);

        g_signal_handlers_disconnect_by_func(test->webView(), reinterpret_cast<void*>(permissionRequestCallback), test);

        return TRUE;
    }

    void waitUntilIsImmersiveModeEnabledChanged()
    {
        g_signal_connect(m_webView.get(), "notify::is-immersive-mode-enabled", G_CALLBACK(isImmersiveModeEnabledChanged), this);
        g_main_loop_run(m_mainLoop);
    }

    void leaveImmersiveModeAndWaitUntilImmersiveModeChanged()
    {
        webkit_web_view_leave_immersive_mode(m_webView.get());

        if (webkit_web_view_is_immersive_mode_enabled(m_webView.get()))
            waitUntilIsImmersiveModeEnabledChanged();
    }

    void clickOnEnterXRButtonAndWaitUntilImmersiveModeChanged()
    {
        g_signal_connect(m_webView.get(), "permission-request", G_CALLBACK(permissionRequestCallback), this);

        m_isExpectingPermissionRequest = true;

        runJavaScriptAndWaitUntilFinished("document.getElementById('enterXR').focus()", nullptr);
        runJavaScriptAndWaitUntilFinished("document.getElementById('enterXR').click();", nullptr);

        if (!webkit_web_view_is_immersive_mode_enabled(m_webView.get()))
            waitUntilIsImmersiveModeEnabledChanged();
    }

    bool m_isExpectingPermissionRequest { false };
};

WebXRTest::WebXRTest()
{
    WebKitSettings* defaultSettings = webkit_web_view_get_settings(m_webView.get());
    relaxDMABufRequirement(defaultSettings);
}

static void serverCallback(SoupServer*, SoupServerMessage* message, const char* path, GHashTable*, gpointer)
{
    g_assert(soup_server_message_get_method(message) == SOUP_METHOD_GET);

    if (g_str_equal(path, "/xr-session/")) {
        soup_server_message_set_status(message, SOUP_STATUS_OK, nullptr);

        auto* responseBody = soup_server_message_get_response_body(message);
        soup_message_body_append(responseBody, SOUP_MEMORY_STATIC, indexHTML, strlen(indexHTML));
        soup_message_body_complete(responseBody);
    } else
        g_assert_not_reached();
}

static void testWebKitWebXRLeaveImmersiveModeAndWaitUntilImmersiveModeChanged(WebXRTest* test, gconstpointer)
{
    WebViewTest::NetworkPolicyGuard guard(test, WEBKIT_TLS_ERRORS_POLICY_IGNORE);

    g_assert_false(webkit_web_view_is_immersive_mode_enabled(test->m_webView.get()));

    test->loadURI(kHttpsServer->getURIForPath("/xr-session/").data());
    test->waitUntilLoadFinished();
    test->showInWindow();

    test->clickOnEnterXRButtonAndWaitUntilImmersiveModeChanged();
    g_assert_true(webkit_web_view_is_immersive_mode_enabled(test->m_webView.get()));

    test->leaveImmersiveModeAndWaitUntilImmersiveModeChanged();
    g_assert_false(webkit_web_view_is_immersive_mode_enabled(test->m_webView.get()));
}

static void testWebKitXRPermissionRequest(WebXRTest* test, gconstpointer)
{
    enum class Answer {
        Deny,
        Allow,
    };
    constexpr auto noFeature = static_cast<WebKitXRSessionFeatures>(0);
    struct Result {
        bool didCallback { false };
        std::optional<WebKitXRSessionMode> mode;
        CString origin;
        WebKitXRSessionFeatures grantedFeatures { noFeature };
        WebKitXRSessionFeatures consentRequiredFeatures { noFeature };
        WebKitXRSessionFeatures consentOptionalFeatures { noFeature };
        WebKitXRSessionFeatures requiredFeaturesRequested { noFeature };
        WebKitXRSessionFeatures optionalFeaturesRequested { noFeature };
        CString title;
    };
    struct Data {
        WebViewTest* test { nullptr };
        Answer answer { Answer::Deny };
        Result result { };

        void resetResult()
        {
            result = Result();
        }
    } data { test };
    typedef gboolean (*PermissionRequestCallback)(WebKitWebView*, WebKitPermissionRequest*, Data*);
    PermissionRequestCallback permissionRequestCallback = [](WebKitWebView*, WebKitPermissionRequest* request, Data* data) -> gboolean {
        g_assert_true(WEBKIT_IS_XR_PERMISSION_REQUEST(request));
        WebKitXRPermissionRequest* xrRequest = WEBKIT_XR_PERMISSION_REQUEST(request);

        data->result.didCallback = true;
        data->result.mode = webkit_xr_permission_request_get_session_mode(xrRequest);
        g_autofree gchar* originStr = webkit_security_origin_to_string(webkit_xr_permission_request_get_security_origin(xrRequest));
        data->result.origin = originStr;
        data->result.grantedFeatures = webkit_xr_permission_request_get_granted_features(xrRequest);
        data->result.consentRequiredFeatures = webkit_xr_permission_request_get_consent_required_features(xrRequest);
        data->result.consentOptionalFeatures = webkit_xr_permission_request_get_consent_optional_features(xrRequest);
        data->result.requiredFeaturesRequested = webkit_xr_permission_request_get_required_features_requested(xrRequest);
        data->result.optionalFeaturesRequested = webkit_xr_permission_request_get_optional_features_requested(xrRequest);

        if (data->answer == Answer::Deny)
            webkit_permission_request_deny(request);
        else
            webkit_permission_request_allow(request);
        return TRUE;
    };

    test->showInWindow();

    auto testPermissionRequest = [&](StringView mode, StringView options, Answer answer) {
        auto script = makeString(
            "async function start() {"
            "    try {"
            "        const session = await navigator.xr.requestSession('"_s, mode, "', {"_s, options, "});"
            "        session.end();"
            "        document.title = 'pass';"
            "    } catch (e) {"
            "        document.title = 'fail';"
            "    }"
            "}"
            "start()"_s);
        data.answer = answer;
        data.resetResult();
        test->loadHtml("", "https://foo.com/bar");
        test->waitUntilLoadFinished();
        test->runJavaScriptAndWaitUntilFinished(script.utf8().data(), nullptr);
        test->waitUntilTitleChanged();
        data.result.title = webkit_web_view_get_title(test->webView());
    };

    // requestSession is rejected by default without a permission-request callback
    testPermissionRequest("immersive-vr"_s, ""_s, Answer::Allow);
    g_assert_false(data.result.didCallback);
    g_assert_cmpstr(data.result.title.data(), ==, "fail");

    // Register permission-request callback
    g_signal_connect(test->webView(), "permission-request", G_CALLBACK(permissionRequestCallback), &data);

    // WebKit grants an inline session without a permission request.
    testPermissionRequest("inline"_s, ""_s, Answer::Deny);
    g_assert_false(data.result.didCallback);
    g_assert_cmpstr(data.result.title.data(), ==, "pass");

    testPermissionRequest("immersive-vr"_s, ""_s, Answer::Deny);
    g_assert_true(data.result.didCallback);
    g_assert_cmpint(data.result.mode.value(), ==, WEBKIT_XR_SESSION_MODE_IMMERSIVE_VR);
    g_assert_cmpstr(data.result.origin.data(), ==, "https://foo.com");
    g_assert_cmpint(data.result.grantedFeatures, ==, WEBKIT_XR_SESSION_FEATURES_VIEWER | WEBKIT_XR_SESSION_FEATURES_LOCAL);
    g_assert_cmpint(data.result.consentRequiredFeatures, ==, noFeature);
    g_assert_cmpint(data.result.consentOptionalFeatures, ==, noFeature);
    g_assert_cmpint(data.result.requiredFeaturesRequested, ==, WEBKIT_XR_SESSION_FEATURES_VIEWER | WEBKIT_XR_SESSION_FEATURES_LOCAL);
    g_assert_cmpint(data.result.optionalFeaturesRequested, ==, noFeature);
    g_assert_cmpstr(data.result.title.data(), ==, "fail");

    // Monado doesn't support hand-tracking
    testPermissionRequest("immersive-ar"_s, "requiredFeatures: ['local', 'unbounded'], optionalFeatures: ['hand-tracking']"_s, Answer::Allow);
    g_assert_true(data.result.didCallback);
    g_assert_cmpint(data.result.mode.value(), ==, WEBKIT_XR_SESSION_MODE_IMMERSIVE_AR);
    g_assert_cmpstr(data.result.origin.data(), ==, "https://foo.com");
    g_assert_cmpint(data.result.grantedFeatures, ==, WEBKIT_XR_SESSION_FEATURES_VIEWER | WEBKIT_XR_SESSION_FEATURES_LOCAL | WEBKIT_XR_SESSION_FEATURES_UNBOUNDED);
    g_assert_cmpint(data.result.consentRequiredFeatures, ==, noFeature);
    g_assert_cmpint(data.result.consentOptionalFeatures, ==, noFeature);
    g_assert_cmpint(data.result.requiredFeaturesRequested, ==, WEBKIT_XR_SESSION_FEATURES_VIEWER | WEBKIT_XR_SESSION_FEATURES_LOCAL | WEBKIT_XR_SESSION_FEATURES_UNBOUNDED);
    g_assert_cmpint(data.result.optionalFeaturesRequested, ==, noFeature);
    g_assert_cmpstr(data.result.title.data(), ==, "pass");
}

static void testWebKitXRHitTest(WebXRTest* test, gconstpointer)
{
    test->showInWindow();

    // Register permission-request callback
    typedef gboolean (*PermissionRequestCallback)(WebKitWebView*, WebKitPermissionRequest*, void*);
    PermissionRequestCallback permissionRequestCallback = [](WebKitWebView*, WebKitPermissionRequest* request, void*) -> gboolean {
        webkit_permission_request_allow(request);
        return TRUE;
    };
    g_signal_connect(test->webView(), "permission-request", G_CALLBACK(permissionRequestCallback), nullptr);

    // Enable WebXRHitTestModule
    g_autoptr(WebKitFeatureList) featureList = webkit_settings_get_experimental_features();
    WebKitFeature* feature = findFeature(featureList, "WebXRHitTestModule");
    g_assert_nonnull(feature);
    auto settings = webkit_web_view_get_settings(test->webView());
    webkit_settings_set_feature_enabled(settings, feature, true);

    auto testHitTest = [&]() {
        auto script = makeString(
            "async function start() {"
            "    try {"
            "        const canvas = document.createElement('canvas');"
            "        document.body.appendChild(canvas);"
            "        const session = await navigator.xr.requestSession('immersive-ar', { requiredFeatures: ['hit-test'] });"
            "        const gl = canvas.getContext('webgl', {xrCompatible: true});"
            "        const layer = new XRWebGLLayer(session, gl);"
            "        session.updateRenderState({ baseLayer: layer });"
            "        const refSpace = await session.requestReferenceSpace('viewer');"
            "        const hitTestSource = await session.requestHitTestSource({ space: refSpace, offsetRay: new XRRay() });"
            "        const frame = await new Promise(resolve => session.requestAnimationFrame((time, frame) => resolve(frame)));"
            "        const hitTestResults = frame.getHitTestResults(hitTestSource);"
            "        session.end();"
            "        document.title = 'pass';"
            "    } catch (e) {"
            "        document.title = e.toString();"
            "    }"
            "}"
            "start()"_s);
        test->loadHtml("", "https://foo.com/bar");
        test->waitUntilLoadFinished();
        test->runJavaScriptAndWaitUntilFinished(script.utf8().data(), nullptr);
        test->waitUntilTitleChanged();
        return CString { webkit_web_view_get_title(test->webView()) };
    };

    // FIXME: requestHitTestSource throws NotSupportedError because the SDK doesn't support XR_ANDROID_raycast yet
    ASSERT_CMP_CSTRING(testHitTest(), ==, "NotSupportedError: The operation is not supported.");
}

void beforeAll()
{
    kHttpsServer = new WebKitTestServer(WebKitTestServer::ServerHTTPS);
    kHttpsServer->run(serverCallback);

    WebXRTest::add("WebKitWebXR", "leave-immersive-mode", testWebKitWebXRLeaveImmersiveModeAndWaitUntilImmersiveModeChanged);
    WebXRTest::add("WebKitWebXR", "permission-request", testWebKitXRPermissionRequest);
    WebXRTest::add("WebKitWebXR", "hit-test", testWebKitXRHitTest);
}

void afterAll()
{
    delete kHttpsServer;
}
