/*
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if WK_HAVE_C_SPI

#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
#include <WebKit/WKContextPrivate.h>
#include <WebKit/WKRetainPtr.h>
#include <string.h>
#include <vector>

using namespace std;

namespace TestWebKitAPI {

enum class GeolocationEvent {
    StartUpdating,
    StopUpdating,
    EnableHighAccuracy,
    DisableHighAccuracy
};

ostream& operator<<(ostream& outputStream, const GeolocationEvent& geolocationEvent)
{
    switch (geolocationEvent) {
    case GeolocationEvent::StartUpdating:
        outputStream << "GeolocationEvent::StartUpdating";
        break;
    case GeolocationEvent::StopUpdating:
        outputStream << "GeolocationEvent::StopUpdating";
        break;
    case GeolocationEvent::EnableHighAccuracy:
        outputStream << "GeolocationEvent::EnableHighAccuracy";
        break;
    case GeolocationEvent::DisableHighAccuracy:
        outputStream << "GeolocationEvent::DisableHighAccuracy";
        break;
    }
    return outputStream;
}

struct GeolocationStateTracker {
    vector<GeolocationEvent> events;

    virtual ~GeolocationStateTracker() { }
    virtual void eventsChanged() { }

    static void startUpdatingCallback(WKGeolocationManagerRef manager, const void* clientInfo)
    {
        GeolocationStateTracker* stateTracker = static_cast<GeolocationStateTracker*>(const_cast<void*>(clientInfo));
        stateTracker->events.push_back(GeolocationEvent::StartUpdating);
        stateTracker->eventsChanged();

        WKRetainPtr<WKGeolocationPositionRef> position = adoptWK(WKGeolocationPositionCreate(0, 50.644358, 3.345453, 2.53));
        WKGeolocationManagerProviderDidChangePosition(manager, position.get());
    }

    static void stopUpdatingCallback(WKGeolocationManagerRef, const void* clientInfo)
    {
        GeolocationStateTracker* stateTracker = static_cast<GeolocationStateTracker*>(const_cast<void*>(clientInfo));
        stateTracker->events.push_back(GeolocationEvent::StopUpdating);
        stateTracker->eventsChanged();
    }

    static void setEnableHighAccuracyCallback(WKGeolocationManagerRef, bool enable, const void* clientInfo)
    {
        GeolocationStateTracker* stateTracker = static_cast<GeolocationStateTracker*>(const_cast<void*>(clientInfo));
        if (enable)
            stateTracker->events.push_back(GeolocationEvent::EnableHighAccuracy);
        else
            stateTracker->events.push_back(GeolocationEvent::DisableHighAccuracy);
        stateTracker->eventsChanged();
    }
};

void decidePolicyForGeolocationPermissionRequestCallBack(WKPageRef page, WKFrameRef frame, WKSecurityOriginRef origin, WKGeolocationPermissionRequestRef permissionRequest, const void* clientInfo)
{
    WKGeolocationPermissionRequestAllow(permissionRequest);
}

void setupGeolocationProvider(WKContextRef context, void* clientInfo)
{
    WKGeolocationProviderV1 providerCallback;
    memset(&providerCallback, 0, sizeof(WKGeolocationProviderV1));

    providerCallback.base.version = 1;
    providerCallback.base.clientInfo = clientInfo;
    providerCallback.startUpdating = GeolocationStateTracker::startUpdatingCallback;
    providerCallback.stopUpdating = GeolocationStateTracker::stopUpdatingCallback;
    providerCallback.setEnableHighAccuracy = GeolocationStateTracker::setEnableHighAccuracyCallback;

    WKGeolocationManagerSetProvider(WKContextGetGeolocationManager(context), &providerCallback.base);
}
    
void clearGeolocationProvider(WKContextRef context)
{
    WKGeolocationManagerSetProvider(WKContextGetGeolocationManager(context), nullptr);
}

void setupView(PlatformWebView& webView)
{
    WKPageUIClientV2 uiClient;
    memset(&uiClient, 0, sizeof(uiClient));

    uiClient.base.version = 2;
    uiClient.decidePolicyForGeolocationPermissionRequest = decidePolicyForGeolocationPermissionRequestCallBack;

    WKPageSetPageUIClient(webView.page(), &uiClient.base);
}

// GeolocationBasic.
struct GeolocationBasicStateTracker : GeolocationStateTracker {
    bool finished;

    GeolocationBasicStateTracker() : finished(false) { }
    virtual void eventsChanged()
    {
        switch (events.size()) {
        case 1:
            EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[0]);
            break;
        case 2:
            EXPECT_EQ(GeolocationEvent::StartUpdating, events[1]);
            break;
        case 3:
            EXPECT_EQ(GeolocationEvent::StopUpdating, events[2]);
            finished = true;
            break;
        default:
            EXPECT_TRUE(false);
            finished = true;
        }
    }
};

TEST(WebKit, GeolocationBasic)
{
    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreateWithConfiguration(nullptr));

    GeolocationBasicStateTracker stateTracker;
    setupGeolocationProvider(context.get(), &stateTracker);

    PlatformWebView webView(context.get());
    setupView(webView);

    WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("geolocationGetCurrentPosition", "html"));
    WKPageLoadURL(webView.page(), url.get());

    Util::run(&stateTracker.finished);
    clearGeolocationProvider(context.get());
}

// Geolocation requested with High Accuracy.
struct GeolocationBasicWithHighAccuracyStateTracker : GeolocationStateTracker {
    bool finished;

    GeolocationBasicWithHighAccuracyStateTracker() : finished(false) { }
    virtual void eventsChanged()
    {
        switch (events.size()) {
        case 1:
            EXPECT_EQ(GeolocationEvent::EnableHighAccuracy, events[0]);
            break;
        case 2:
            EXPECT_EQ(GeolocationEvent::StartUpdating, events[1]);
            break;
        case 3:
            EXPECT_EQ(GeolocationEvent::StopUpdating, events[2]);
            finished = true;
            break;
        default:
            EXPECT_TRUE(false);
            finished = true;
        }
    }
};

TEST(WebKit, GeolocationBasicWithHighAccuracy)
{
    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreateWithConfiguration(nullptr));

    GeolocationBasicWithHighAccuracyStateTracker stateTracker;
    setupGeolocationProvider(context.get(), &stateTracker);

    PlatformWebView webView(context.get());
    setupView(webView);

    WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("geolocationGetCurrentPositionWithHighAccuracy", "html"));
    WKPageLoadURL(webView.page(), url.get());

    Util::run(&stateTracker.finished);
    clearGeolocationProvider(context.get());
}

// Geolocation start without High Accuracy, then requires High Accuracy.
struct GeolocationTransitionToHighAccuracyStateTracker : GeolocationStateTracker {
    bool finishedFirstStep { false };
    bool enabledHighAccuracy { false };
    bool finished { false };

    virtual void eventsChanged()
    {
        switch (events.size()) {
        case 1:
            EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[0]);
            break;
        case 2:
            EXPECT_EQ(GeolocationEvent::StartUpdating, events[1]);
            finishedFirstStep = true;
            break;
        case 3:
            EXPECT_EQ(GeolocationEvent::EnableHighAccuracy, events[2]);
            enabledHighAccuracy = true;
            break;
        case 4:
            EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[3]);
            break;
        case 5:
            EXPECT_EQ(GeolocationEvent::StopUpdating, events[4]);
            finished = true;
            break;
        default:
            EXPECT_TRUE(false);
            finishedFirstStep = true;
            enabledHighAccuracy = true;
            finished = true;
        }
    }
};

TEST(WebKit, GeolocationTransitionToHighAccuracy)
{
    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreateWithConfiguration(nullptr));

    GeolocationTransitionToHighAccuracyStateTracker stateTracker;
    setupGeolocationProvider(context.get(), &stateTracker);

    PlatformWebView lowAccuracyWebView(context.get());
    setupView(lowAccuracyWebView);
    WKRetainPtr<WKURLRef> lowAccuracyURL = adoptWK(Util::createURLForResource("geolocationWatchPosition", "html"));
    WKPageLoadURL(lowAccuracyWebView.page(), lowAccuracyURL.get());
    Util::run(&stateTracker.finishedFirstStep);

    PlatformWebView highAccuracyWebView(lowAccuracyWebView.page());
    setupView(highAccuracyWebView);
    WKRetainPtr<WKURLRef> highAccuracyURL = adoptWK(Util::createURLForResource("geolocationWatchPositionWithHighAccuracy", "html"));
    WKPageLoadURL(highAccuracyWebView.page(), highAccuracyURL.get());
    Util::run(&stateTracker.enabledHighAccuracy);
    
    WKRetainPtr<WKURLRef> resetUrl = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
    WKPageLoadURL(highAccuracyWebView.page(), resetUrl.get());
    Util::run(&stateTracker.enabledHighAccuracy);
    WKPageLoadURL(lowAccuracyWebView.page(), resetUrl.get());
    Util::run(&stateTracker.finished);

    clearGeolocationProvider(context.get());
}

// Geolocation start with High Accuracy, then should fall back to low accuracy.
struct GeolocationTransitionToLowAccuracyStateTracker : GeolocationStateTracker {
    bool finishedFirstStep { false };
    bool disabledHighAccuracy { false };
    bool finished { false };

    virtual void eventsChanged()
    {
        switch (events.size()) {
        case 1:
            EXPECT_EQ(GeolocationEvent::EnableHighAccuracy, events[0]);
            break;
        case 2:
            EXPECT_EQ(GeolocationEvent::StartUpdating, events[1]);
            finishedFirstStep = true;
            break;
        case 3:
            EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[2]);
            disabledHighAccuracy = true;
            break;
        case 4:
            EXPECT_EQ(GeolocationEvent::StopUpdating, events[3]);
            finished = true;
            break;
        default:
            EXPECT_TRUE(false);
            finishedFirstStep = true;
            disabledHighAccuracy = true;
            finished = true;
        }
    }
};

struct JavaScriptAlertContext {
    bool didRun { false };
    std::string alertText;
};

static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, const void* clientInfo)
{
    auto* context = static_cast<JavaScriptAlertContext*>(const_cast<void*>(clientInfo));
    context->didRun = true;
    context->alertText = Util::toSTD(alertText);
}

TEST(WebKit, GeolocationTransitionToLowAccuracy)
{
    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreateWithConfiguration(nullptr));

    GeolocationTransitionToLowAccuracyStateTracker stateTracker;
    setupGeolocationProvider(context.get(), &stateTracker);

    PlatformWebView highAccuracyWebView(context.get());
    setupView(highAccuracyWebView);
    WKRetainPtr<WKURLRef> highAccuracyURL = adoptWK(Util::createURLForResource("geolocationWatchPositionWithHighAccuracy", "html"));
    WKPageLoadURL(highAccuracyWebView.page(), highAccuracyURL.get());
    Util::run(&stateTracker.finishedFirstStep);

    PlatformWebView lowAccuracyWebView(context.get());
    setupView(lowAccuracyWebView);

    JavaScriptAlertContext secondStepContext;

    WKPageUIClientV2 uiClient;
    memset(&uiClient, 0, sizeof(uiClient));
    uiClient.base.version = 2;
    uiClient.base.clientInfo = &secondStepContext;
    uiClient.decidePolicyForGeolocationPermissionRequest = decidePolicyForGeolocationPermissionRequestCallBack;
    uiClient.runJavaScriptAlert = runJavaScriptAlert;
    WKPageSetPageUIClient(lowAccuracyWebView.page(), &uiClient.base);

    WKRetainPtr<WKURLRef> lowAccuracyURL = adoptWK(Util::createURLForResource("geolocationWatchPosition", "html"));
    WKPageLoadURL(lowAccuracyWebView.page(), lowAccuracyURL.get());
    Util::run(&secondStepContext.didRun);
    EXPECT_EQ(secondStepContext.alertText, "SUCCESS");

    WKRetainPtr<WKURLRef> resetUrl = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
    WKPageLoadURL(highAccuracyWebView.page(), resetUrl.get());

    Util::run(&stateTracker.disabledHighAccuracy);

    WKPageLoadURL(lowAccuracyWebView.page(), resetUrl.get());
    Util::run(&stateTracker.finished);

    clearGeolocationProvider(context.get());
}

TEST(WebKit, GeolocationWatchMultiprocess)
{
    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreateWithConfiguration(nullptr));

    GeolocationStateTracker stateTracker;
    setupGeolocationProvider(context.get(), &stateTracker);

    JavaScriptAlertContext testContext;

    WKPageUIClientV2 uiClient;
    memset(&uiClient, 0, sizeof(uiClient));
    uiClient.base.version = 2;
    uiClient.base.clientInfo = &testContext;
    uiClient.decidePolicyForGeolocationPermissionRequest = decidePolicyForGeolocationPermissionRequestCallBack;
    uiClient.runJavaScriptAlert = runJavaScriptAlert;

    PlatformWebView view1(context.get());
    WKPageSetPageUIClient(view1.page(), &uiClient.base);
    WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("geolocationWatchPosition", "html"));
    WKPageLoadURL(view1.page(), url.get());
    Util::run(&testContext.didRun);
    EXPECT_EQ(testContext.alertText, "SUCCESS");
    WKPageSetPageUIClient(view1.page(), nullptr);

    testContext.didRun = false;
    testContext.alertText = { };

    PlatformWebView view2(context.get());
    WKPageSetPageUIClient(view2.page(), &uiClient.base);
    WKPageLoadURL(view2.page(), url.get());
    Util::run(&testContext.didRun);
    EXPECT_EQ(testContext.alertText, "SUCCESS");

    clearGeolocationProvider(context.get());
}

} // namespace TestWebKitAPI

#endif
