/*
 * Copyright (C) 2021 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"
#import "DisplayCaptureSessionManager.h"

#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)

#import "Logging.h"
#import "MediaPermissionUtilities.h"
#import "WKWebViewInternal.h"
#import "WebPageProxy.h"
#import <WebCore/CaptureDeviceManager.h>
#import <WebCore/LocalizedStrings.h>
#import <WebCore/MockRealtimeMediaSourceCenter.h>
#import <WebCore/ScreenCaptureKitCaptureSource.h>
#import <WebCore/SecurityOriginData.h>
#import <wtf/BlockPtr.h>
#import <wtf/MainThread.h>
#import <wtf/NeverDestroyed.h>
#import <wtf/URLHelpers.h>
#import <wtf/cocoa/TypeCastsCocoa.h>
#import <wtf/text/StringToIntegerConversion.h>

namespace WebKit {

#if HAVE(SCREEN_CAPTURE_KIT)

static void alertForWindowSelection(WebPageProxy& page, const WebCore::SecurityOriginData& origin, CompletionHandler<void(std::optional<String>, std::optional<String>)>&& completionHandler)
{
    auto webView = page.cocoaView();
    if (!webView) {
        completionHandler(std::nullopt, std::nullopt);
        return;
    }

    Vector<DisplayCaptureManager::WindowCaptureDevice> windowInfo;
    RealtimeMediaSourceCenter::singleton().displayCaptureFactory().displayCaptureDeviceManager().windowDevices(windowInfo);
    if (windowInfo.isEmpty()) {
        completionHandler(std::nullopt, std::nullopt);
        return;
    }

    std::sort(windowInfo.begin(), windowInfo.end(), [](auto& a, auto& b) {
        if (a.m_application != b.m_application)
            return codePointCompareLessThan(a.m_application, b.m_application);

        return codePointCompareLessThan(a.m_device.label(), b.m_device.label());
    });

    auto alert = adoptNS([[NSAlert alloc] init]);
    [alert setMessageText:WEB_UI_NSSTRING(@"Choose a window to share", Message for window sharing prompt)];

    auto popupButton = adoptNS([[NSPopUpButton alloc] initWithFrame:NSMakeRect(10, 0, 290, 36) pullsDown:NO]);
    auto menu = [popupButton menu];
    menu.autoenablesItems = NO;
    String currentApplication;
    unsigned infoIndex = 0;
    for (auto& info : windowInfo) {
        if (info.m_application != currentApplication)    {
            auto applicationItem = adoptNS([[NSMenuItem alloc] initWithTitle:info.m_application action:nil keyEquivalent:@""]);
            [applicationItem setEnabled:NO];
            [menu addItem:applicationItem.get()];
            currentApplication = info.m_application;
        }

        auto title = info.m_device.label();
        auto windowItem = adoptNS([[NSMenuItem alloc] initWithTitle:(!title.isEmpty() ? title : info.m_application) action:nil keyEquivalent:@""]);
        [windowItem setIndentationLevel:1];
        [windowItem setRepresentedObject:@(infoIndex++)];
        [menu addItem:windowItem.get()];
    }
    [popupButton selectItem:nil];

    auto menuLabel = adoptNS([[NSTextView alloc] init]);
    [menuLabel setString:WEB_UI_NSSTRING(@"Window: ", "Label for window sharing menu")];
    [menuLabel setDrawsBackground:NO];
    [menuLabel setSelectable:NO];
    [menuLabel setEditable:NO];

    auto accessoryView = adoptNS([[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 40)]);
    [accessoryView addSubview:popupButton.get()];
    [accessoryView addSubview:menuLabel.get()];
    [alert setAccessoryView:accessoryView.get()];

    NSButton *button = [alert addButtonWithTitle:WEB_UI_NSSTRING(@"Allow (window sharing)", "Allow button title in window sharing prompt")];
    button.keyEquivalent = @"";
    button = [alert addButtonWithTitle:WEB_UI_NSSTRING(@"Don’t Allow (window sharing)", "Disallow button title in window sharing prompt")];
    button.keyEquivalent = @"\E";

    [alert beginSheetModalForWindow:[webView window] completionHandler:[popupButton = WTFMove(popupButton), windowInfo, completionBlock = makeBlockPtr(WTFMove(completionHandler))](NSModalResponse returnCode) {
        if (returnCode != NSAlertFirstButtonReturn) {
            completionBlock(std::nullopt, std::nullopt);
            return;
        }

        NSNumber *infoIndex = [[popupButton selectedItem] representedObject];
        if (!infoIndex || [infoIndex unsignedIntegerValue] > windowInfo.size()) {
            completionBlock(std::nullopt, std::nullopt);
            return;
        }

        auto info = windowInfo[[infoIndex unsignedIntegerValue]];
        completionBlock(info.m_device.persistentId(), info.m_device.label());
    }];
}

void DisplayCaptureSessionManager::alertForGetDisplayMedia(WebPageProxy& page, const WebCore::SecurityOriginData& origin, CompletionHandler<void(DisplayCaptureSessionManager::CaptureSessionType)>&& completionHandler)
{

    auto webView = page.cocoaView();
    if (!webView) {
        completionHandler(DisplayCaptureSessionManager::CaptureSessionType::None);
        return;
    }

    NSString *visibleOrigin = applicationVisibleNameFromOrigin(origin);
    if (!visibleOrigin)
        visibleOrigin = applicationVisibleName();

    NSString *alertTitle = [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to observe one of your windows or screens?", "Message for window and screen sharing prompt"), visibleOrigin];
    auto *allowWindowButtonString = WEB_UI_NSSTRING(@"Allow Observing a Window", "Allow window button title in window and screen sharing prompt");
    auto *allowScreenButtonString = WEB_UI_NSSTRING(@"Allow Observing a Screen", "Allow screen button title in window and screen sharing prompt");
    auto *doNotAllowButtonString = WEB_UI_NSSTRING(@"Don’t Allow (window and screen sharing)", "Disallow button title in window and screen sharing prompt");

    auto alert = adoptNS([[NSAlert alloc] init]);
    [alert setMessageText:alertTitle];

    auto *button = [alert addButtonWithTitle:allowWindowButtonString];
    button.keyEquivalent = @"";

    button = [alert addButtonWithTitle:allowScreenButtonString];
    button.keyEquivalent = @"";

    button = [alert addButtonWithTitle:doNotAllowButtonString];
    button.keyEquivalent = @"\E";

    [alert beginSheetModalForWindow:[webView window] completionHandler:[completionBlock = makeBlockPtr(WTFMove(completionHandler))](NSModalResponse returnCode) {
        DisplayCaptureSessionManager::CaptureSessionType result = DisplayCaptureSessionManager::CaptureSessionType::None;
        switch (returnCode) {
        case NSAlertFirstButtonReturn:
            result = DisplayCaptureSessionManager::CaptureSessionType::Window;
            break;
        case NSAlertSecondButtonReturn:
            result = DisplayCaptureSessionManager::CaptureSessionType::Screen;
            break;
        case NSAlertThirdButtonReturn:
            result = DisplayCaptureSessionManager::CaptureSessionType::None;
            break;
        }

        completionBlock(result);
    }];
}

std::optional<CaptureDevice> DisplayCaptureSessionManager::deviceSelectedForTesting(CaptureDevice::DeviceType deviceType)
{
    ASSERT(m_indexOfDeviceSelectedForTesting);

    unsigned index = 0;
    for (auto& device : RealtimeMediaSourceCenter::singleton().displayCaptureFactory().displayCaptureDeviceManager().captureDevices()) {
        if (device.enabled() && device.type() == deviceType) {
            if (index == m_indexOfDeviceSelectedForTesting.value())
                return { device };
            ++index;
        }
    }

    return std::nullopt;
}

void DisplayCaptureSessionManager::showWindowPicker(WebPageProxy& page, const WebCore::SecurityOriginData& origin, CompletionHandler<void(std::optional<CaptureDevice>)>&& completionHandler)
{
    if (m_indexOfDeviceSelectedForTesting) {
        completionHandler(deviceSelectedForTesting(CaptureDevice::DeviceType::Window));
        return;
    }

    alertForWindowSelection(page, origin, [completionHandler = WTFMove(completionHandler)] (std::optional<String> windowID, std::optional<String> windowTitle) mutable {

        if (!windowID || !windowTitle) {
            completionHandler(std::nullopt);
            return;
        }

        CaptureDevice device = { windowID.value(), CaptureDevice::DeviceType::Window, windowTitle.value(), emptyString(), true };
        completionHandler({ device });
    });
}

void DisplayCaptureSessionManager::showScreenPicker(WebPageProxy&, const WebCore::SecurityOriginData&, CompletionHandler<void(std::optional<CaptureDevice>)>&& completionHandler)
{
    if (m_indexOfDeviceSelectedForTesting) {
        completionHandler(deviceSelectedForTesting(CaptureDevice::DeviceType::Screen));
        return;
    }

    callOnMainRunLoop([completionHandler = WTFMove(completionHandler)] () mutable {
        for (auto& device : RealtimeMediaSourceCenter::singleton().displayCaptureFactory().displayCaptureDeviceManager().captureDevices()) {
            if (device.enabled() && device.type() == CaptureDevice::DeviceType::Screen) {
                completionHandler({ device });
                return;
            }
        }

        completionHandler(std::nullopt);
    });
}
#endif

bool DisplayCaptureSessionManager::isAvailable()
{
#if HAVE(SCREEN_CAPTURE_KIT)
    return ScreenCaptureKitCaptureSource::isAvailable();
#else
    return false;
#endif
}

DisplayCaptureSessionManager& DisplayCaptureSessionManager::singleton()
{
    ASSERT(isMainRunLoop());
    static NeverDestroyed<DisplayCaptureSessionManager> manager;
    return manager;
}

DisplayCaptureSessionManager::DisplayCaptureSessionManager()
{
}

DisplayCaptureSessionManager::~DisplayCaptureSessionManager()
{
}

void DisplayCaptureSessionManager::promptForGetDisplayMedia(UserMediaPermissionRequestProxy::UserMediaDisplayCapturePromptType promptType, WebPageProxy& page, const WebCore::SecurityOriginData& origin, CompletionHandler<void(std::optional<CaptureDevice>)>&& completionHandler)
{
    ASSERT(isAvailable());

#if HAVE(SCREEN_CAPTURE_KIT)
    if (!isAvailable() || !completionHandler) {
        completionHandler(std::nullopt);
        return;
    }

    if (promptType == UserMediaPermissionRequestProxy::UserMediaDisplayCapturePromptType::Screen) {
        showScreenPicker(page, origin, WTFMove(completionHandler));
        return;
    }

    if (promptType == UserMediaPermissionRequestProxy::UserMediaDisplayCapturePromptType::Window) {
        showWindowPicker(page, origin, WTFMove(completionHandler));
        return;
    }

    alertForGetDisplayMedia(page, origin, [this, page = Ref { page }, origin, completionHandler = WTFMove(completionHandler)] (DisplayCaptureSessionManager::CaptureSessionType sessionType) mutable {
        if (sessionType == CaptureSessionType::None) {
            completionHandler(std::nullopt);
            return;
        }

        if (sessionType == CaptureSessionType::Screen)
            showScreenPicker(page, origin, WTFMove(completionHandler));
        else
            showWindowPicker(page, origin, WTFMove(completionHandler));
    });
#else
    completionHandler(std::nullopt);
#endif

}
} // namespace WebKit

#endif // PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
