/*
 * Copyright (C) 2020 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.
 */

#import "config.h"

#if USE(APPLE_INTERNAL_SDK)

#import "InstanceMethodSwizzler.h"
#import "PlatformUtilities.h"
#import "Test.h"
#import "TestURLSchemeHandler.h"
#import "TestWKWebView.h"
#import "VirtualGamepad.h"
#import <WebKit/WKProcessPoolPrivate.h>

@interface GamepadMessageHandler : NSObject <WKScriptMessageHandler>
@property (readonly, nonatomic) Vector<RetainPtr<NSString>> messages;
@end

static bool didReceiveMessage = false;

@implementation GamepadMessageHandler

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    _messages.append(message.body);
    didReceiveMessage = true;
}
@end

namespace TestWebKitAPI {

static const char* mainBytes = R"GAMEPADRESOURCE(
<script>

function handleGamepadConnect(evt)
{
    window.webkit.messageHandlers.gamepad.postMessage(JSON.stringify(evt.gamepad.id));
}

function handleGamepadDisconnect(evt)
{
    window.webkit.messageHandlers.gamepad.postMessage("Disconnect: " + JSON.stringify(evt.gamepad.id));
}

addEventListener("gamepadconnected", handleGamepadConnect);
addEventListener("gamepaddisconnected", handleGamepadDisconnect);

</script>
)GAMEPADRESOURCE";

static NSWindow *keyWindowForTesting;
static NSWindow *getKeyWindowForTesting()
{
    return keyWindowForTesting;
}

TEST(Gamepad, Basic)
{
    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];

    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
        [task didFinish];
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView window];
    [webView.get().configuration.processPool _setUsesOnlyHIDGamepadProviderForTesting:YES];

    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];

    [[webView window] makeFirstResponder:webView.get()];

    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
    // needs to convince it to monitor gamepad devices
    [[webView window] resignKeyWindow];
    [[webView window] makeKeyWindow];

    // Create a gamepad with a fake vendorID
    auto mapping = VirtualGamepad::steelSeriesNimbusMapping();
    mapping.vendorID = HIDVendorID::Fake;
    auto gamepad = makeUnique<VirtualGamepad>(mapping);
    while (![webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting])
        Util::sleep(0.1);

    // Press a button on it, waiting for the web page to see it
    gamepad->setButtonValue(0, 1.0);
    gamepad->publishReport();

    Util::run(&didReceiveMessage);
    didReceiveMessage = false;

    EXPECT_EQ(messageHandler.get().messages.size(), 1u);
    EXPECT_TRUE([messageHandler.get().messages[0] isEqualToString:@"\"ffff-1420-Virtual Nimbus\""]);
    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting], 1u);
}

TEST(Gamepad, GCFVersusHID)
{
    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];

    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
        [task didFinish];
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView window];
    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];

    [[webView window] makeFirstResponder:webView.get()];

    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
    // needs to convince it to monitor gamepad devices
    [[webView window] resignKeyWindow];
    [[webView window] makeKeyWindow];

    static const size_t TestGamepadCount = 5;
    std::unique_ptr<VirtualGamepad> gamepads[TestGamepadCount];

    // Create gamepads that should go through GameController.framework
    gamepads[0] = makeUnique<VirtualGamepad>(VirtualGamepad::steelSeriesNimbusMapping());
    gamepads[1] = makeUnique<VirtualGamepad>(VirtualGamepad::microsoftXboxOneMapping());
    gamepads[2] = makeUnique<VirtualGamepad>(VirtualGamepad::sonyDualshock4Mapping());

    // Create one that should go through HID
    gamepads[3] = makeUnique<VirtualGamepad>(VirtualGamepad::shenzhenLongshengweiTechnologyGamepadMapping());

    // Create one that GameController framework tries to handle, but shouldn't:
    // Make sure HID handles it instead.
    gamepads[4] = makeUnique<VirtualGamepad>(VirtualGamepad::sunLightApplicationGenericNESMapping());

    while ([webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting] != TestGamepadCount)
        Util::sleep(0.1);

    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedHIDGamepadsForTesting], 2u);
    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedGameControllerFrameworkGamepadsForTesting], 3u);

    // Press buttons on them, waiting for the web page to see them
    for (size_t i = 0; i < TestGamepadCount; ++i) {
        gamepads[i]->setButtonValue(0, 1.0);
        gamepads[i]->publishReport();
    }

    // The page messages back once for each controller
    while (messageHandler.get().messages.size() < TestGamepadCount) {
        didReceiveMessage = false;
        Util::run(&didReceiveMessage);
    }

    NSSet *expectedGamepadNames = [NSSet setWithArray:@[
        @"\"Virtual Nimbus Extended Gamepad\"",
        @"\"Virtual Dualshock4 Extended Gamepad\"",
        @"\"Virtual Xbox One Gamepad\"",
        @"\"Virtual Xbox One Extended Gamepad\"",
        @"\"79-11-Virtual Shenzhen Longshengwei Technology Gamepad\"",
        @"\"12bd-d015-Virtual Sun Light Application Generic NES Controller\""]];

    for (size_t i = 0; i < TestGamepadCount; ++i)
        EXPECT_TRUE([expectedGamepadNames containsObject:messageHandler.get().messages[i].get()]);

    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedHIDGamepadsForTesting], 2u);
    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedGameControllerFrameworkGamepadsForTesting], 3u);
}

static const char* pollGamepadStateFunction = R"GAMEPADRESOURCE(
var result = new Object();
var gamepads = navigator.getGamepads();
result.gamepadCount = gamepads.length;
result.gamepadButtons = new Array;
result.gamepadAxes = new Array;
result.gamepadMapping = new Array;

for (var i = 0; i < gamepads.length; ++i) {
    result.gamepadButtons[i] = new Array;
    for (var j = 0; j < gamepads[i].buttons.length; ++j)
        result.gamepadButtons[i][j] = gamepads[i].buttons[j].value;

    result.gamepadAxes[i] = new Array;
    for (var j = 0; j < gamepads[i].axes.length; ++j)
        result.gamepadAxes[i][j] = gamepads[i].axes[j];

    result.gamepadMapping[i] = gamepads[i].mapping;
}

return result;

)GAMEPADRESOURCE";

TEST(Gamepad, GamepadState)
{
    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];

    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
        [task didFinish];
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView window];
    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];

    [[webView window] makeFirstResponder:webView.get()];

    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
    // needs to convince it to monitor gamepad devices
    [[webView window] resignKeyWindow];
    [[webView window] makeKeyWindow];

    // Connect a gamepad and make it visible to the page
    auto gamepad = makeUnique<VirtualGamepad>(VirtualGamepad::shenzhenLongshengweiTechnologyGamepadMapping());
    while (![webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting])
        Util::sleep(0.01);

    Vector<double> expectedButtons = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
    Vector<double> expectedAxes = { -0.9921568627450981, -0.003921568627450966, -0.003921568627450966, -0.003921568627450966, -0.003921568627450966 };

    auto updateStateAndPublish = [&] {
        for (size_t i = 0; i < expectedButtons.size(); ++i)
            gamepad->setButtonValue(i, expectedButtons[i]);
        for (size_t i = 0; i < 5; ++i)
            gamepad->setAxisValue(i, expectedAxes[i]);
        gamepad->publishReport();
    };

    updateStateAndPublish();

    // Wait for the page to tell us a gamepad connected
    Util::run(&didReceiveMessage);
    didReceiveMessage = false;

    EXPECT_EQ(messageHandler.get().messages.size(), 1u);
    EXPECT_TRUE([messageHandler.get().messages[0] isEqualToString:@"\"79-11-Virtual Shenzhen Longshengwei Technology Gamepad\""]);

    bool done = false;
    bool gotNewValues = false;
    auto resultBlock = [&] (id result, NSError *error) {
        EXPECT_NULL(error);
        EXPECT_TRUE([result[@"gamepadCount"] isEqualToNumber:@(1)]);

        bool areEqual = true;

        for (size_t i = 0; i < 10; ++i) {
            if (!WTF::areEssentiallyEqual([(NSNumber *)result[@"gamepadButtons"][0][i] doubleValue], expectedButtons[i]))
                areEqual = false;
        }

        for (size_t i = 0; i < 5; ++i) {
            if (!WTF::areEssentiallyEqual([(NSNumber *)result[@"gamepadAxes"][0][i] doubleValue], expectedAxes[i]))
                areEqual = false;
        }

        if (areEqual)
            gotNewValues = true;

        done = true;
    };

    // Change some buttons, polling state to confirm
    NSDate *start = [NSDate date];
    while (!gotNewValues) {
        [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
        Util::run(&done);
        done = false;

        if ([[NSDate date] timeIntervalSinceDate:start] > 1.0)
            break;
    }
    EXPECT_TRUE(gotNewValues);
    gotNewValues = false;

    expectedButtons = { 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0 };
    updateStateAndPublish();

    start = [NSDate date];
    while (!gotNewValues) {
        [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
        Util::run(&done);
        done = false;

        if ([[NSDate date] timeIntervalSinceDate:start] > 1.0)
            break;
    }
    EXPECT_TRUE(gotNewValues);
    gotNewValues = false;

    expectedAxes = { -1.0, -1.0, -1.0, -1.0, 1.0 };
    updateStateAndPublish();

    // Even though we set -1.0 for each "X" axis, the first 3 axes on this controller are always constant
    expectedAxes = { -0.9921568627450981, -0.003921568627450966, -0.003921568627450966, -1.0, 1.0 };

    start = [NSDate date];
    while (!gotNewValues) {
        [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
        Util::run(&done);
        done = false;

        if ([[NSDate date] timeIntervalSinceDate:start] > 1.0)
            break;
    }
    EXPECT_TRUE(gotNewValues);
    gotNewValues = false;

    // Disconnect the gamepad
    gamepad = nullptr;

    Util::run(&didReceiveMessage);
    didReceiveMessage = false;

    EXPECT_EQ(messageHandler.get().messages.size(), 2u);
    EXPECT_TRUE([messageHandler.get().messages[1] isEqualToString:@"Disconnect: \"79-11-Virtual Shenzhen Longshengwei Technology Gamepad\""]);
}

TEST(Gamepad, Dualshock3Basic)
{
    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];

    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
        [task didFinish];
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView window];
    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];

    [[webView window] makeFirstResponder:webView.get()];

    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
    // needs to convince it to monitor gamepad devices
    [[webView window] resignKeyWindow];
    [[webView window] makeKeyWindow];

    // Connect a gamepad and make it visible to the page
    auto gamepad = makeUnique<VirtualGamepad>(VirtualGamepad::sonyDualshock3Mapping());
    while (![webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting])
        Util::sleep(0.01);

    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedHIDGamepadsForTesting], 1u);
    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedGameControllerFrameworkGamepadsForTesting], 0u);

    gamepad->setButtonValue(0, 0.75);
    gamepad->publishReport();

    // Wait for the page to tell us a gamepad connected
    Util::run(&didReceiveMessage);
    didReceiveMessage = false;

    EXPECT_EQ(messageHandler.get().messages.size(), 1u);
    EXPECT_TRUE([messageHandler.get().messages[0] isEqualToString:@"\"54c-268-Virtual Dualshock3\""]);

    bool done = false;
    auto resultBlock = [&] (id result, NSError *error) {
        EXPECT_NULL(error);
        EXPECT_TRUE([result[@"gamepadCount"] isEqualToNumber:@(1)]);
        EXPECT_EQ(((NSArray *)result[@"gamepadButtons"][0]).count, 17u);
        EXPECT_EQ(((NSArray *)result[@"gamepadAxes"][0]).count, 4u);

        done = true;
    };

    [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];

    Util::run(&done);
    didReceiveMessage = true;
}

TEST(Gamepad, Stadia)
{
    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];

    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
        [task didFinish];
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView window];
    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];

    [[webView window] makeFirstResponder:webView.get()];

    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
    // needs to convince it to monitor gamepad devices
    [[webView window] resignKeyWindow];
    [[webView window] makeKeyWindow];

    // Connect a gamepad and make it visible to the page
    auto gamepad = makeUnique<VirtualGamepad>(VirtualGamepad::googleStadiaMapping());
    while (![webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting])
        Util::sleep(0.01);

    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedHIDGamepadsForTesting], 1u);
    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedGameControllerFrameworkGamepadsForTesting], 0u);

    gamepad->setButtonValue(0, 1.0);
    gamepad->setButtonValue(1, 1.0);
    gamepad->setButtonValue(2, 1.0);
    gamepad->setButtonValue(3, 1.0);
    gamepad->setButtonValue(4, 1.0);
    gamepad->setButtonValue(5, 1.0);
    gamepad->publishReport();

    // Wait for the page to tell us a gamepad connected
    Util::run(&didReceiveMessage);
    didReceiveMessage = false;

    EXPECT_EQ(messageHandler.get().messages.size(), 1u);
    EXPECT_TRUE([messageHandler.get().messages[0] isEqualToString:@"\"18d1-9400-Virtual Stadia\""]);

    bool done = false;
    auto resultBlock = [&] (id result, NSError *error) {
        EXPECT_NULL(error);
        EXPECT_TRUE([result[@"gamepadCount"] isEqualToNumber:@(1)]);
        EXPECT_EQ(((NSArray *)result[@"gamepadButtons"][0]).count, 19u);
        EXPECT_EQ(((NSArray *)result[@"gamepadAxes"][0]).count, 4u);

        done = true;
    };

    [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];

    Util::run(&done);
    didReceiveMessage = true;
}

TEST(Gamepad, LogitechBasic)
{
    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];

    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
        [task didFinish];
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView window];
    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];

    [[webView window] makeFirstResponder:webView.get()];

    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
    // needs to convince it to monitor gamepad devices
    [[webView window] resignKeyWindow];
    [[webView window] makeKeyWindow];
    [[webView window] makeFirstResponder:webView.get()];

    // Connect a gamepad and make it visible to the page
    auto gamepad1 = makeUnique<VirtualGamepad>(VirtualGamepad::logitechF310Mapping());
    auto gamepad2 = makeUnique<VirtualGamepad>(VirtualGamepad::logitechF710Mapping());
    while ([webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting] != 2u)
        Util::sleep(0.01);

    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedHIDGamepadsForTesting], 2u);
    EXPECT_EQ([webView.get().configuration.processPool _numberOfConnectedGameControllerFrameworkGamepadsForTesting], 0u);

    gamepad1->setButtonValue(0, 1.0);
    gamepad2->setButtonValue(0, 1.0);
    gamepad1->publishReport();
    gamepad2->publishReport();

    // The page messages back once for each controller
    while (messageHandler.get().messages.size() < 2) {
        didReceiveMessage = false;
        Util::run(&didReceiveMessage);
    }

    EXPECT_EQ(messageHandler.get().messages.size(), 2u);
    EXPECT_TRUE([messageHandler.get().messages[0] isEqualToString:@"\"46d-c216-Virtual Logitech F310\""]);

    NSSet *expectedGamepadNames = [NSSet setWithArray:@[
        @"\"46d-c216-Virtual Logitech F310\"",
        @"\"46d-c219-Virtual Logitech F710\""]];

    for (size_t i = 0; i < 2; ++i)
        EXPECT_TRUE([expectedGamepadNames containsObject:messageHandler.get().messages[i].get()]);

    bool done = false;
    auto resultBlock = [&] (id result, NSError *error) {
        EXPECT_NULL(error);
        EXPECT_TRUE([result[@"gamepadCount"] isEqualToNumber:@(2)]);
        EXPECT_EQ(((NSArray *)result[@"gamepadButtons"][0]).count, 16u);
        EXPECT_EQ(((NSArray *)result[@"gamepadButtons"][1]).count, 16u);
        EXPECT_EQ(((NSArray *)result[@"gamepadAxes"][0]).count, 4u);
        EXPECT_EQ(((NSArray *)result[@"gamepadAxes"][1]).count, 4u);

        done = true;
    };

    [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];

    Util::run(&done);
    didReceiveMessage = true;
}

TEST(Gamepad, FullInfoAfterConnection)
{
    auto keyWindowSwizzler = makeUnique<InstanceMethodSwizzler>([NSApplication class], @selector(keyWindow), reinterpret_cast<IMP>(getKeyWindowForTesting));

    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
    auto messageHandler = adoptNS([[GamepadMessageHandler alloc] init]);
    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gamepad"];

    auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]);
    [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"gamepad"];

    [schemeHandler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
        [task didReceiveResponse:response.get()];
        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
        [task didFinish];
    }];

    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView window];
    [webView synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];

    [[webView window] makeFirstResponder:webView.get()];

    // Resigning/reinstating the key window state triggers the "key window did change" notification that WKWebView currently
    // needs to convince it to monitor gamepad devices
    [[webView window] resignKeyWindow];
    [[webView window] makeKeyWindow];

    // Connect a gamepad and make it visible to the page
    auto gamepad1 = makeUnique<VirtualGamepad>(VirtualGamepad::logitechF310Mapping());
    while ([webView.get().configuration.processPool _numberOfConnectedGamepadsForTesting] != 1u)
        Util::sleep(0.01);

    gamepad1->setButtonValue(0, 1.0);
    gamepad1->publishReport();

    // Wait until the page sees the gamepad
    while (messageHandler.get().messages.size() < 1) {
        didReceiveMessage = false;
        Util::run(&didReceiveMessage);
    }

    bool done = false;
    auto resultBlock = [&] (id result, NSError *error) {
        EXPECT_NULL(error);
        EXPECT_TRUE([result[@"gamepadCount"] isEqualToNumber:@(1)]);
        EXPECT_TRUE([result[@"gamepadMapping"][0] isEqualToString:@"standard"]);
        done = true;
    };

    // Verify the gamepad has the expected mapping.
    [webView callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
    Util::run(&done);
    done = false;

    // Make a second web view to make the same gamepad visible to it.
    auto webView2 = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
    keyWindowForTesting = [webView2 window];
    [webView2 synchronouslyLoadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"gamepad://host/main.html"]]];
    [[webView2 window] makeFirstResponder:webView2.get()];

    // The gamepad is already connected, but this new web view can't see it.
    // Press buttons to make it visible.
    gamepad1->setButtonValue(1, 1.0);
    gamepad1->publishReport();

    // The gamepad is already connected, but this new web view can't see it.
    // Press buttons to make it visible.
    while (messageHandler.get().messages.size() < 2) {
        didReceiveMessage = false;
        Util::run(&didReceiveMessage);
    }

    // Verify the gamepad has the expected mapping in the second web view.
    [webView2 callAsyncJavaScript:@(pollGamepadStateFunction) arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:resultBlock];
    Util::run(&done);
    done = false;
}


} // namespace TestWebKitAPI

#endif // USE(APPLE_INTERNAL_SDK)
