/*
 * 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 PLATFORM(MAC) && ENABLE(MEDIA_SESSION)

#import "PlatformUtilities.h"
#import "Test.h"
#import "TestWKWebView.h"
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WebViewPrivate.h>
#import <pal/spi/mac/MediaRemoteSPI.h>
#import <wtf/Function.h>
#import <wtf/HashSet.h>
#import <wtf/NeverDestroyed.h>
#import <wtf/SoftLinking.h>
#import <wtf/text/StringHash.h>
#import <wtf/text/WTFString.h>

SOFT_LINK_PRIVATE_FRAMEWORK(MediaRemote)

SOFT_LINK(MediaRemote, MRMediaRemoteSendCommandToApp, Boolean, (MRMediaRemoteCommand command, CFDictionaryRef options, MROriginRef origin, CFStringRef appDisplayID, MRSendCommandAppOptions appOptions, dispatch_queue_t replyQ, void(^completion)(MRSendCommandError err, CFArrayRef handlerReturnStatuses)), (command, options, origin, appDisplayID, appOptions, replyQ, completion));
#define MRMediaRemoteSendCommandToApp softLinkMRMediaRemoteSendCommandToApp

SOFT_LINK(MediaRemote, MRMediaRemoteGetLocalOrigin, MROriginRef, (), ());
#define MRMediaRemoteGetLocalOrigin softLinkMRMediaRemoteGetLocalOrigin

SOFT_LINK(MediaRemote, MRMediaRemoteGetSupportedCommandsForOrigin, void, (MROriginRef origin, dispatch_queue_t queue, void(^completion)(CFArrayRef commands)), (origin, queue, completion));
#define MRMediaRemoteGetSupportedCommandsForOrigin softLinkMRMediaRemoteGetSupportedCommandsForOrigin

SOFT_LINK(MediaRemote, MRMediaRemoteGetNowPlayingClient, void, (dispatch_queue_t queue, void(^completion)(MRNowPlayingClientRef, CFErrorRef)), (queue, completion))
#define MRMediaRemoteGetNowPlayingClient softLinkMRMediaRemoteGetNowPlayingClient

SOFT_LINK(MediaRemote, MRNowPlayingClientGetProcessIdentifier, pid_t, (MRNowPlayingClientRef client), (client))
#define MRNowPlayingClientGetProcessIdentifier softLinkMRNowPlayingClientGetProcessIdentifier

SOFT_LINK_CONSTANT(MediaRemote, kMRMediaRemoteOptionSkipInterval, CFStringRef)
#define kMRMediaRemoteOptionSkipInterval getkMRMediaRemoteOptionSkipInterval()

SOFT_LINK_CONSTANT(MediaRemote, kMRMediaRemoteOptionPlaybackPosition, CFStringRef)
#define kMRMediaRemoteOptionPlaybackPosition getkMRMediaRemoteOptionPlaybackPosition()

#if !USE(APPLE_INTERNAL_SDK)
@interface MRCommandInfo : NSObject
@property (nonatomic, readonly) MRMediaRemoteCommand command;
@property (nonatomic, readonly, getter=isEnabled) BOOL enabled;
@property (nonatomic, readonly, copy) NSDictionary *options;
@end
#endif

namespace TestWebKitAPI {

class MediaSessionTest : public testing::Test {
public:
    void SetUp() final
    {
        _configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
        [_configuration setMediaTypesRequiringUserActionForPlayback:WKAudiovisualMediaTypeAudio];

        _webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:_configuration.get() addToWindow:YES]);

        WKPreferences *preferences = [_webView configuration].preferences;
        preferences._mediaSessionEnabled = YES;

        _messageHandlers = adoptNS([[NSMutableArray alloc] init]);
    }

    void TearDown() override
    {
        [_webView clearMessageHandlers:_messageHandlers.get()];
    }

    TestWKWebView* webView() { return _webView.get(); }

    pid_t webViewPid() { return [_webView _webProcessIdentifier]; }

    RetainPtr<MRNowPlayingClientRef> getNowPlayingClient()
    {
        bool gotNowPlaying = false;
        RetainPtr<MRNowPlayingClientRef> nowPlayingClient;
        MRMediaRemoteGetNowPlayingClient(dispatch_get_main_queue(), [&] (MRNowPlayingClientRef player, CFErrorRef error) {
            if (!error && player)
                nowPlayingClient = player;
            gotNowPlaying = true;
        });
        TestWebKitAPI::Util::run(&gotNowPlaying);
        return nowPlayingClient;
    }

    pid_t getNowPlayingClientPid()
    {
        return MRNowPlayingClientGetProcessIdentifier(getNowPlayingClient().get());
    }

    void loadPageAndBecomeNowPlaying(const String& pageName)
    {
        [_webView synchronouslyLoadTestPageNamed:pageName];

        bool canplaythrough = false;
        [webView() performAfterReceivingMessage:@"canplaythrough event" action:[&] {
            canplaythrough = true;
        }];
        runScriptWithUserGesture("load()");
        Util::run(&canplaythrough);

        play();
        pause();
        ASSERT_EQ(webViewPid(), getNowPlayingClientPid());
    }

    void runScriptWithUserGesture(const String& script)
    {
        bool complete = false;
        [_webView evaluateJavaScript:script completionHandler:[&] (id, NSError *) { complete = true; }];
        TestWebKitAPI::Util::run(&complete);
    }

    void play()
    {
        bool playing = false;
        [_webView performAfterReceivingMessage:@"play event" action:[&] { playing = true; }];
        runScriptWithUserGesture("audio.play()");
        Util::run(&playing);
    }

    void pause()
    {
        bool paused = false;
        [_webView performAfterReceivingMessage:@"pause event" action:[&] { paused = true; }];
        runScriptWithUserGesture("audio.pause()");
        Util::run(&paused);
    }

    bool sendMediaRemoteCommand(MRMediaRemoteCommand command, CFDictionaryRef options = nullptr)
    {
        bool completed = false;
        bool success;

        MRMediaRemoteSendCommandToApp(command, options, NULL, NULL, static_cast<MRSendCommandAppOptions>(0), NULL, [&] (MRSendCommandError error, CFArrayRef) {
            success = !error;
            completed = true;
        });
        TestWebKitAPI::Util::run(&completed);

        return success;
    }

    bool sendMediaRemoteSeekCommand(MRMediaRemoteCommand command, double interval)
    {
        CFStringRef seekInterval = (command == MRMediaRemoteCommandSeekToPlaybackPosition) ? kMRMediaRemoteOptionPlaybackPosition : kMRMediaRemoteOptionSkipInterval;
        NSDictionary *options = @{(__bridge NSString *)seekInterval : @(interval)};
        return sendMediaRemoteCommand(command, (__bridge CFDictionaryRef)options);
    }

    void listenForEventMessages(std::initializer_list<const char*> events)
    {
        for (auto* event : events) {
            auto eventMessage = makeString(event, " event");
            [_messageHandlers addObject:eventMessage];
            [webView() performAfterReceivingMessage:eventMessage action:[this, eventMessage = WTFMove(eventMessage)] {
                _eventListenersCalled.add(eventMessage);
            }];
        }
    }

    bool eventListenerWasCalled(const String& event)
    {
        return _eventListenersCalled.contains(makeString(event, " event"));
    }

    void clearEventListenerState()
    {
        _eventListenersCalled.clear();
    }

    void waitForEventListenerToBeCalled(const String& event)
    {
        int tries = 0;
        do {
            if (eventListenerWasCalled(event))
                return;
            Util::sleep(0.1);
        } while (++tries <= 50);

        return;
    }

    void listenForSessionHandlerMessages(std::initializer_list<const char*> handlers)
    {
        for (auto* handler : handlers) {
            auto handlerMessage = makeString(handler, " handler");
            [_messageHandlers addObject:handlerMessage];
            [webView() performAfterReceivingMessage:handlerMessage action:[this, handlerMessage = WTFMove(handlerMessage)] {
                _mediaSessionHandlersCalled.add(handlerMessage);
            }];
        }
    }

    bool sessionHandlerWasCalled(const String& handler)
    {
        return _mediaSessionHandlersCalled.contains(makeString(handler, " handler"));
    }

    void waitForSessionHandlerToBeCalled(const String& handler)
    {
        int tries = 0;
        do {
            if (sessionHandlerWasCalled(handler))
                return;
            Util::sleep(0.1);
        } while (++tries <= 50);

        return;
    }

    RetainPtr<NSArray> getSupportedCommands()
    {
        bool completed = false;
        RetainPtr<NSArray> result;

        MRMediaRemoteGetSupportedCommandsForOrigin(MRMediaRemoteGetLocalOrigin(), dispatch_get_main_queue(), [&] (CFArrayRef commands) {
            result = (__bridge NSArray *)commands;
            completed = true;
        });

        TestWebKitAPI::Util::run(&completed);

        return result;
    }

private:
    RetainPtr<WKWebViewConfiguration> _configuration;
    RetainPtr<TestWKWebView> _webView;

    HashSet<String> _mediaSessionHandlersCalled;
    HashSet<String> _eventListenersCalled;
    RetainPtr<NSMutableArray> _messageHandlers;
};

TEST_F(MediaSessionTest, DISABLED_OnlyOneHandler)
{
    loadPageAndBecomeNowPlaying("media-remote");

    [webView() objectByEvaluatingJavaScript:@"setEmptyActionHandlers([ 'play' ])"];

    listenForSessionHandlerMessages({ "play", "pause", "seekto", "seekforward", "seekbackward", "previoustrack", "nexttrack" });
    listenForEventMessages({ "play", "pause", "seeked" });

#if __MAC_OS_X_VERSION_MIN_REQUIRED > 101500
    static Vector<MRMediaRemoteCommand> registeredCommands = { MRMediaRemoteCommandPlay };
    auto currentCommands = getSupportedCommands();
    for (MRCommandInfo *command in currentCommands.get()) {
        if (!command.enabled)
            continue;
        
        ASSERT_TRUE(registeredCommands.contains(command.command));
    }
#endif

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandPlay));
    waitForSessionHandlerToBeCalled("play");
    ASSERT_TRUE(sessionHandlerWasCalled("play"));
    ASSERT_FALSE(eventListenerWasCalled("play"));

    // The media session only registered for Play, but no other commands should reach HTMLMediaElement.
    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSkipForward, 1));
    ASSERT_FALSE(sessionHandlerWasCalled("seekforward"));
    ASSERT_FALSE(eventListenerWasCalled("seeked"));

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSkipBackward, 10));
    ASSERT_FALSE(sessionHandlerWasCalled("seekbackward"));
    ASSERT_FALSE(eventListenerWasCalled("seeked"));

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSeekToPlaybackPosition, 6));
    ASSERT_FALSE(sessionHandlerWasCalled("seekto"));
    ASSERT_FALSE(eventListenerWasCalled("seeked"));

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandNextTrack));
    ASSERT_FALSE(sessionHandlerWasCalled("nexttrack"));

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandPreviousTrack));
    ASSERT_FALSE(sessionHandlerWasCalled("previoustrack"));
}

TEST_F(MediaSessionTest, DISABLED_RemoteCommands)
{
    loadPageAndBecomeNowPlaying("media-remote");

    [webView() objectByEvaluatingJavaScript:@"setEmptyActionHandlers([ 'play', 'pause', 'seekto', 'seekforward', 'seekbackward', 'previoustrack', 'nexttrack' ])"];

    listenForSessionHandlerMessages({ "play", "pause", "seekto", "seekforward", "seekbackward", "previoustrack", "nexttrack" });
    listenForEventMessages({ "play", "pause", "seeked" });

#if __MAC_OS_X_VERSION_MIN_REQUIRED > 101500
    static Vector<MRMediaRemoteCommand> registeredCommands = { MRMediaRemoteCommandPlay, MRMediaRemoteCommandPause, MRMediaRemoteCommandSeekToPlaybackPosition, MRMediaRemoteCommandSkipForward, MRMediaRemoteCommandSkipBackward, MRMediaRemoteCommandPreviousTrack, MRMediaRemoteCommandNextTrack };
    auto currentCommands = getSupportedCommands();
    for (MRCommandInfo *command in currentCommands.get()) {
        if (!command.enabled)
            continue;
        
        ASSERT_TRUE(registeredCommands.contains(command.command));
    }
#endif

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandPlay));
    waitForSessionHandlerToBeCalled("play");
    ASSERT_TRUE(sessionHandlerWasCalled("play"));
    ASSERT_FALSE(eventListenerWasCalled("play"));

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandPause));
    waitForSessionHandlerToBeCalled("pause");
    ASSERT_TRUE(sessionHandlerWasCalled("pause"));
    ASSERT_FALSE(eventListenerWasCalled("pause"));

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSkipForward, 1));
    waitForSessionHandlerToBeCalled("seekforward");
    ASSERT_TRUE(sessionHandlerWasCalled("seekforward"));
    ASSERT_FALSE(eventListenerWasCalled("seeked"));

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSkipBackward, 10));
    waitForSessionHandlerToBeCalled("seekbackward");
    ASSERT_TRUE(sessionHandlerWasCalled("seekbackward"));
    ASSERT_FALSE(eventListenerWasCalled("seeked"));

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSeekToPlaybackPosition, 6));
    waitForSessionHandlerToBeCalled("seekto");
    ASSERT_TRUE(sessionHandlerWasCalled("seekto"));
    ASSERT_FALSE(eventListenerWasCalled("seeked"));

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandNextTrack));
    waitForSessionHandlerToBeCalled("nexttrack");
    ASSERT_TRUE(sessionHandlerWasCalled("nexttrack"));

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandPreviousTrack));
    waitForSessionHandlerToBeCalled("previoustrack");
    ASSERT_TRUE(sessionHandlerWasCalled("previoustrack"));

    // Unregister action handlers, supported commands should go to HTMLMediaElement.
    [webView() objectByEvaluatingJavaScript:@"clearActionHandlers()"];
    clearEventListenerState();

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandPlay));
    waitForEventListenerToBeCalled("play");
    ASSERT_TRUE(eventListenerWasCalled("play"));

    ASSERT_TRUE(sendMediaRemoteCommand(MRMediaRemoteCommandPause));
    waitForEventListenerToBeCalled("pause");
    ASSERT_TRUE(eventListenerWasCalled("pause"));

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSkipForward, 1));
    waitForEventListenerToBeCalled("seeked");
    ASSERT_TRUE(eventListenerWasCalled("seeked"));
    clearEventListenerState();

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSkipBackward, 10));
    waitForEventListenerToBeCalled("seeked");
    ASSERT_TRUE(eventListenerWasCalled("seeked"));
    clearEventListenerState();

    ASSERT_TRUE(sendMediaRemoteSeekCommand(MRMediaRemoteCommandSeekToPlaybackPosition, 6));
    waitForEventListenerToBeCalled("seeked");
    ASSERT_TRUE(eventListenerWasCalled("seeked"));
}

}

#endif // PLATFORM(MAC) && ENABLE(MEDIA_SESSION)
