/*
 * Copyright (C) 2019 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 "TestMain.h"

#include "WebViewTest.h"
#include <wtf/WallTime.h>

class GeolocationTest: public WebViewTest {
public:
    MAKE_GLIB_TEST_FIXTURE(GeolocationTest);

    struct Position {
        double timestamp { std::numeric_limits<double>::quiet_NaN() };
        double latitude { std::numeric_limits<double>::quiet_NaN() };
        double longitude { std::numeric_limits<double>::quiet_NaN() };
        double accuracy { std::numeric_limits<double>::quiet_NaN() };

        std::optional<double> altitude;
        std::optional<double> altitudeAccuracy;
        std::optional<double> heading;
        std::optional<double> speed;
    };

    static gboolean startCallback(WebKitGeolocationManager* manager, GeolocationTest* test)
    {
        g_assert_true(test->m_manager == manager);
        test->start();
        return TRUE;
    }

    static void stopCallback(WebKitGeolocationManager* manager, GeolocationTest* test)
    {
        g_assert_true(test->m_manager == manager);
        test->stop();
    }

    static gboolean permissionRequested(WebKitWebView*, WebKitPermissionRequest* request, GeolocationTest* test)
    {
        g_assert_true(WEBKIT_IS_PERMISSION_REQUEST(request));
        test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));

        if (WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(request)) {
            webkit_permission_request_allow(request);
            return TRUE;
        }

        return FALSE;
    }

    GeolocationTest()
        : m_manager(webkit_web_context_get_geolocation_manager(m_webContext.get()))
    {
        g_assert_true(WEBKIT_IS_GEOLOCATION_MANAGER(m_manager));
        assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_manager));
        g_signal_connect(m_manager, "start", G_CALLBACK(startCallback), this);
        g_signal_connect(m_manager, "stop", G_CALLBACK(stopCallback), this);
        g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequested), this);
    }

    ~GeolocationTest()
    {
        if (m_checkPosition)
            webkit_geolocation_position_free(m_checkPosition);

        g_signal_handlers_disconnect_matched(m_manager, G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
        g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
    }

    void start()
    {
        g_assert_false(m_updating);
        m_updating = true;

        if (m_errorMessage) {
            g_assert_false(m_checkPosition);
            webkit_geolocation_manager_failed(m_manager, m_errorMessage.get());
        }

        if (m_checkPosition) {
            g_assert_false(m_errorMessage.get());
            webkit_geolocation_manager_update_position(m_manager, m_checkPosition);
        }

        g_main_loop_quit(m_mainLoop);
    }

    void stop()
    {
        g_assert_true(m_updating);
        m_updating = false;
        if (m_watching)
            g_main_loop_quit(m_mainLoop);
    }

    Position lastPosition()
    {
        GUniqueOutPtr<GError> error;
        auto* javascriptResult = runJavaScriptAndWaitUntilFinished("position", &error.outPtr());
        g_assert_nonnull(javascriptResult);
        g_assert_no_error(error.get());

        auto* jsPosition = webkit_javascript_result_get_js_value(javascriptResult);
        g_assert_true(jsc_value_is_object(jsPosition));
        Position result;
        GRefPtr<JSCValue> value = adoptGRef(jsc_value_object_get_property(jsPosition, "latitude"));
        g_assert_true(jsc_value_is_number(value.get()));
        result.latitude = jsc_value_to_double(value.get());
        value = adoptGRef(jsc_value_object_get_property(jsPosition, "longitude"));
        g_assert_true(jsc_value_is_number(value.get()));
        result.longitude = jsc_value_to_double(value.get());
        value = adoptGRef(jsc_value_object_get_property(jsPosition, "accuracy"));
        g_assert_true(jsc_value_is_number(value.get()));
        result.accuracy = jsc_value_to_double(value.get());
        value = adoptGRef(jsc_value_object_get_property(jsPosition, "altitude"));
        if (!jsc_value_is_null(value.get())) {
            g_assert_true(jsc_value_is_number(value.get()));
            result.altitude = jsc_value_to_double(value.get());
        }
        value = adoptGRef(jsc_value_object_get_property(jsPosition, "altitudeAccuracy"));
        if (!jsc_value_is_null(value.get())) {
            g_assert_true(jsc_value_is_number(value.get()));
            result.altitudeAccuracy = jsc_value_to_double(value.get());
        }
        value = adoptGRef(jsc_value_object_get_property(jsPosition, "heading"));
        if (!jsc_value_is_null(value.get())) {
            g_assert_true(jsc_value_is_number(value.get()));
            result.heading = jsc_value_to_double(value.get());
        }
        value = adoptGRef(jsc_value_object_get_property(jsPosition, "speed"));
        if (!jsc_value_is_null(value.get())) {
            g_assert_true(jsc_value_is_number(value.get()));
            result.speed = jsc_value_to_double(value.get());
        }
        value = adoptGRef(jsc_value_object_get_property(jsPosition, "timestamp"));
        g_assert_true(jsc_value_is_number(value.get()));
        result.timestamp = jsc_value_to_double(value.get());
        return result;
    }

    Position checkCurrentPosition(WebKitGeolocationPosition* position, bool enableHighAccuracy = false)
    {
        g_clear_pointer(&m_checkPosition, webkit_geolocation_position_free);
        m_checkPosition = position;

        static const char getCurrentPosition[] =
            "var position = null;\n"
            "options = { enableHighAccuracy: %s }\n"
            "navigator.geolocation.getCurrentPosition(function(p) {\n"
            "  position = { };\n"
            "  position.latitude = p.coords.latitude;\n"
            "  position.longitude = p.coords.longitude;\n"
            "  position.accuracy = p.coords.accuracy;\n"
            "  position.altitude = p.coords.altitude;\n"
            "  position.altitudeAccuracy = p.coords.altitudeAccuracy;\n"
            "  position.heading = p.coords.heading;\n"
            "  position.speed = p.coords.speed;\n"
            "  position.timestamp = p.timestamp;\n"
            "}, undefined, options);";
        GUniquePtr<char> script(g_strdup_printf(getCurrentPosition, enableHighAccuracy ? "true" : "false"));
        GUniqueOutPtr<GError> error;
        runJavaScriptAndWaitUntilFinished(script.get(), &error.outPtr());
        g_assert_no_error(error.get());
        g_main_loop_run(m_mainLoop);
        g_clear_pointer(&m_checkPosition, webkit_geolocation_position_free);
        g_assert_true(webkit_geolocation_manager_get_enable_high_accuracy(m_manager) == enableHighAccuracy);

        return lastPosition();
    }

    GUniquePtr<char> checkFailedToDeterminePosition(const char* errorMessage)
    {
        m_errorMessage.reset(g_strdup(errorMessage));
        static const char getCurrentPosition[] =
            "var error;\n"
            "navigator.geolocation.getCurrentPosition(\n"
            "  function(p) { error = null; },\n"
            "  function(e) { error = e.message.toString(); }\n"
            ");";
        GUniqueOutPtr<GError> error;
        auto* javascriptResult = runJavaScriptAndWaitUntilFinished(getCurrentPosition, &error.outPtr());
        g_assert_no_error(error.get());
        g_main_loop_run(m_mainLoop);
        m_errorMessage = nullptr;

        javascriptResult = runJavaScriptAndWaitUntilFinished("error", &error.outPtr());
        g_assert_nonnull(javascriptResult);
        g_assert_no_error(error.get());
        auto* jsErrorMessage = webkit_javascript_result_get_js_value(javascriptResult);
        g_assert_true(jsc_value_is_string(jsErrorMessage));
        return GUniquePtr<char>(jsc_value_to_string(jsErrorMessage));
    }

    void startWatch()
    {
        g_clear_pointer(&m_checkPosition, webkit_geolocation_position_free);
        m_errorMessage = nullptr;

        m_watching = true;
        static const char watchPosition[] =
            "var position = null;\n"
            "var watchID = navigator.geolocation.watchPosition(function(p) {\n"
            "  position = { };\n"
            "  position.latitude = p.coords.latitude;\n"
            "  position.longitude = p.coords.longitude;\n"
            "  position.accuracy = p.coords.accuracy;\n"
            "  position.altitude = p.coords.altitude;\n"
            "  position.altitudeAccuracy = p.coords.altitudeAccuracy;\n"
            "  position.heading = p.coords.heading;\n"
            "  position.speed = p.coords.speed;\n"
            "  position.timestamp = p.timestamp;\n"
            "});";
        GUniqueOutPtr<GError> error;
        auto* javascriptResult = runJavaScriptAndWaitUntilFinished(watchPosition, &error.outPtr());
        g_assert_nonnull(javascriptResult);
        g_assert_no_error(error.get());
        g_main_loop_run(m_mainLoop);
    }

    void stopWatch()
    {
        GUniqueOutPtr<GError> error;
        runJavaScriptAndWaitUntilFinished("navigator.geolocation.clearWatch(watchID)", &error.outPtr());
        g_assert_no_error(error.get());
        g_main_loop_run(m_mainLoop);
        m_watching = false;
    }

    WebKitGeolocationManager* m_manager;
    bool m_updating { false };
    bool m_watching { false };
    WebKitGeolocationPosition* m_checkPosition { nullptr };
    GUniquePtr<char> m_errorMessage;
};

static void testGeolocationManagerCurrentPosition(GeolocationTest* test, gconstpointer)
{
    test->showInWindow();
    test->loadHtml("<html><body></body></html>", "https://foo.com/bar");
    test->waitUntilLoadFinished();

    WebKitGeolocationPosition* position = webkit_geolocation_position_new(37.1760783, -3.59033, 17);
    g_assert_false(test->m_updating);
    auto result = test->checkCurrentPosition(position);
    g_assert_false(test->m_updating);
    g_assert_cmpfloat(result.latitude, ==, 37.1760783);
    g_assert_cmpfloat(result.longitude, ==, -3.59033);
    g_assert_cmpfloat(result.accuracy, ==, 17);
    g_assert_false(result.altitude);
    g_assert_false(result.altitudeAccuracy);
    g_assert_false(result.heading);
    g_assert_false(result.speed);
    g_assert_cmpfloat(result.timestamp, >, 0);
    g_assert_cmpfloat(result.timestamp / 1000., <, WallTime::now().secondsSinceEpoch().value());

    position = webkit_geolocation_position_new(27.986065, 86.922623, 0);
    auto timestamp = WallTime::now().secondsSinceEpoch();
    webkit_geolocation_position_set_timestamp(position, timestamp.value());
    webkit_geolocation_position_set_altitude(position, 8495);
    webkit_geolocation_position_set_altitude_accuracy(position, 0);
    webkit_geolocation_position_set_heading(position, 100.55);
    webkit_geolocation_position_set_speed(position, 0.05);
    g_assert_false(test->m_updating);
    result = test->checkCurrentPosition(position, true);
    g_assert_false(test->m_updating);
    g_assert_cmpfloat(result.latitude, ==, 27.986065);
    g_assert_cmpfloat(result.longitude, ==, 86.922623);
    g_assert_cmpfloat(result.accuracy, ==, 0);
    g_assert_true(result.altitude);
    g_assert_cmpfloat(result.altitude.value(), ==, 8495);
    g_assert_true(result.altitudeAccuracy);
    g_assert_cmpfloat(result.altitudeAccuracy.value(), ==, 0);
    g_assert_true(result.heading);
    g_assert_cmpfloat(result.heading.value(), ==, 100.55);
    g_assert_true(result.speed);
    g_assert_cmpfloat(result.speed.value(), ==, 0.05);
    g_assert_cmpfloat_with_epsilon(result.timestamp / 1000., timestamp.value(), 1);

    auto errorMessage = test->checkFailedToDeterminePosition("GPS is not active");
    g_assert_cmpstr(errorMessage.get(), ==, "GPS is not active");
}

static void testGeolocationManagerWatchPosition(GeolocationTest* test, gconstpointer)
{
    test->showInWindow();
    test->loadHtml("<html><body></body></html>", "https://foo.com/bar");
    test->waitUntilLoadFinished();

    test->startWatch();
    g_assert_true(test->m_updating);

    WebKitGeolocationPosition* position = webkit_geolocation_position_new(37.1760783, -3.59033, 17);
    webkit_geolocation_manager_update_position(test->m_manager, position);
    webkit_geolocation_position_free(position);
    auto result = test->lastPosition();
    g_assert_cmpfloat(result.latitude, ==, 37.1760783);
    g_assert_cmpfloat(result.longitude, ==, -3.59033);
    g_assert_cmpfloat(result.accuracy, ==, 17);

    position = webkit_geolocation_position_new(38.1770783, -3.60033, 17);
    webkit_geolocation_manager_update_position(test->m_manager, position);
    webkit_geolocation_position_free(position);
    result = test->lastPosition();
    g_assert_cmpfloat(result.latitude, ==, 38.1770783);
    g_assert_cmpfloat(result.longitude, ==, -3.60033);
    g_assert_cmpfloat(result.accuracy, ==, 17);

    test->stopWatch();
    g_assert_false(test->m_updating);
}

void beforeAll()
{
    GeolocationTest::add("WebKitGeolocationManager", "current-position", testGeolocationManagerCurrentPosition);
    GeolocationTest::add("WebKitGeolocationManager", "watch-position", testGeolocationManagerWatchPosition);
}

void afterAll()
{
}
