/*
 * Copyright (C) 2010-2022 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 "WebContextMenuProxyMac.h"

#if PLATFORM(MAC)

#import "APIAttachment.h"
#import "APIContextMenuClient.h"
#import "MenuUtilities.h"
#import "PageClientImplMac.h"
#import "ServicesController.h"
#import "ShareableBitmap.h"
#import "WKMenuItemIdentifiersPrivate.h"
#import "WKSharingServicePickerDelegate.h"
#import "WebContextMenuItem.h"
#import "WebContextMenuItemData.h"
#import "WebPageProxy.h"
#import "WebPreferences.h"
#import <WebCore/GraphicsContext.h>
#import <WebCore/IntRect.h>
#import <WebCore/LocalizedStrings.h>
#import <pal/spi/mac/NSMenuSPI.h>
#import <pal/spi/mac/NSSharingServicePickerSPI.h>
#import <pal/spi/mac/NSWindowSPI.h>
#import <wtf/BlockPtr.h>
#import <wtf/RetainPtr.h>

@interface WKUserDataWrapper : NSObject {
    RefPtr<API::Object> _webUserData;
}
- (id)initWithUserData:(API::Object*)userData;
- (API::Object*)userData;
@end

@implementation WKUserDataWrapper

- (id)initWithUserData:(API::Object*)userData
{
    self = [super init];
    if (!self)
        return nil;
    
    _webUserData = userData;
    return self;
}

- (API::Object*)userData
{
    return _webUserData.get();
}

@end

@interface WKSelectionHandlerWrapper : NSObject {
    WTF::Function<void ()> _selectionHandler;
}
- (id)initWithSelectionHandler:(WTF::Function<void ()>&&)selectionHandler;
- (void)executeSelectionHandler;
@end

@implementation WKSelectionHandlerWrapper
- (id)initWithSelectionHandler:(WTF::Function<void ()>&&)selectionHandler
{
    self = [super init];
    if (!self)
        return nil;
    
    _selectionHandler = WTFMove(selectionHandler);
    return self;
}

- (void)executeSelectionHandler
{
    if (_selectionHandler)
        _selectionHandler();
}
@end

@interface WKMenuTarget : NSObject {
    WebKit::WebContextMenuProxyMac* _menuProxy;
}
+ (WKMenuTarget *)sharedMenuTarget;
- (WebKit::WebContextMenuProxyMac*)menuProxy;
- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy;
- (void)forwardContextMenuAction:(id)sender;
@end

@implementation WKMenuTarget

+ (WKMenuTarget*)sharedMenuTarget
{
    static WKMenuTarget* target = [[WKMenuTarget alloc] init];
    return target;
}

- (WebKit::WebContextMenuProxyMac*)menuProxy
{
    return _menuProxy;
}

- (void)setMenuProxy:(WebKit::WebContextMenuProxyMac*)menuProxy
{
    _menuProxy = menuProxy;
}

- (void)forwardContextMenuAction:(id)sender
{
    id representedObject = [sender representedObject];

    // NSMenuItems with a represented selection handler belong solely to the UI process
    // and don't need any further processing after the selection handler is called.
    if ([representedObject isKindOfClass:[WKSelectionHandlerWrapper class]]) {
        [representedObject executeSelectionHandler];
        return;
    }

    ASSERT(!sender || [sender isKindOfClass:NSMenuItem.class]);
    WebKit::WebContextMenuItemData item(WebCore::ActionType, static_cast<WebCore::ContextMenuAction>([sender tag]), [sender title], [sender isEnabled], [(NSMenuItem *)sender state] == NSControlStateValueOn);
    if (representedObject) {
        ASSERT([representedObject isKindOfClass:[WKUserDataWrapper class]]);
        item.setUserData([static_cast<WKUserDataWrapper *>(representedObject) userData]);
    }

    _menuProxy->contextMenuItemSelected(item);
}

@end

@interface WKMenuDelegate : NSObject <NSMenuDelegate> {
    WebKit::WebContextMenuProxyMac* _menuProxy;
}
-(instancetype)initWithMenuProxy:(WebKit::WebContextMenuProxyMac&)menuProxy;
@end

@implementation WKMenuDelegate

-(instancetype)initWithMenuProxy:(WebKit::WebContextMenuProxyMac&)menuProxy
{
    if (!(self = [super init]))
        return nil;

    _menuProxy = &menuProxy;

    return self;
}

#pragma mark - NSMenuDelegate

- (void)menuWillOpen:(NSMenu *)menu
{
    _menuProxy->page()->didShowContextMenu();
}

- (void)menuDidClose:(NSMenu *)menu
{
    _menuProxy->page()->didDismissContextMenu();
}

@end

namespace WebKit {
using namespace WebCore;

WebContextMenuProxyMac::WebContextMenuProxyMac(NSView *webView, WebPageProxy& page, ContextMenuContextData&& context, const UserData& userData)
    : WebContextMenuProxy(page, WTFMove(context), userData)
    , m_webView(webView)
{
}

WebContextMenuProxyMac::~WebContextMenuProxyMac()
{
    [m_menu cancelTracking];
}

void WebContextMenuProxyMac::contextMenuItemSelected(const WebContextMenuItemData& item)
{
#if ENABLE(SERVICE_CONTROLS)
    clearServicesMenu();
#endif

    page()->contextMenuItemSelected(item);
}

#if ENABLE(SERVICE_CONTROLS)
void WebContextMenuProxyMac::setupServicesMenu()
{
    bool includeEditorServices = m_context.controlledDataIsEditable();
    bool hasControlledImage = m_context.controlledImage();
    NSArray *items = nil;
    if (hasControlledImage) {
        RefPtr<ShareableBitmap> image = m_context.controlledImage();
        if (!image)
            return;

        auto cgImage = image->makeCGImage();
        auto nsImage = adoptNS([[NSImage alloc] initWithCGImage:cgImage.get() size:image->size()]);

ALLOW_DEPRECATED_DECLARATIONS_BEGIN
        auto itemProvider = adoptNS([[NSItemProvider alloc] initWithItem:[nsImage TIFFRepresentation] typeIdentifier:(__bridge NSString *)kUTTypeTIFF]);
ALLOW_DEPRECATED_DECLARATIONS_END
        items = @[ itemProvider.get() ];
    } else if (!m_context.controlledSelectionData().isEmpty()) {
        auto selectionData = adoptNS([[NSData alloc] initWithBytes:static_cast<const void*>(m_context.controlledSelectionData().data()) length:m_context.controlledSelectionData().size()]);
        auto selection = adoptNS([[NSAttributedString alloc] initWithRTFD:selectionData.get() documentAttributes:nil]);

        items = @[ selection.get() ];
    } else {
        LOG_ERROR("No service controlled item represented in the context");
        return;
    }

    RetainPtr<NSSharingServicePicker> picker = adoptNS([[NSSharingServicePicker alloc] initWithItems:items]);
    [picker setStyle:hasControlledImage ? NSSharingServicePickerStyleRollover : NSSharingServicePickerStyleTextSelection];
    [picker setDelegate:[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate]];
    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setPicker:picker.get()];
    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setFiltersEditingServices:!includeEditorServices];
    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setHandlesEditingReplacement:includeEditorServices];
    
    NSRect imageRect = m_context.controlledImageBounds();
    imageRect = [m_webView convertRect:imageRect toView:nil];
    imageRect = [[m_webView window] convertRectToScreen:imageRect];
    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setSourceFrame:imageRect];
    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setAttachmentID:m_context.controlledImageAttachmentID()];

    m_menu = adoptNS([[picker menu] copy]);

    if (!hasControlledImage)
        [m_menu setShowsStateColumn:YES];

    // Explicitly add a menu item for each telephone number that is in the selection.
    Vector<RetainPtr<NSMenuItem>> telephoneNumberMenuItems;

    for (auto& telephoneNumber : m_context.selectedTelephoneNumbers()) {
        if (NSMenuItem *item = menuItemForTelephoneNumber(telephoneNumber)) {
            [item setIndentationLevel:1];
            telephoneNumberMenuItems.append(item);
        }
    }

    if (!telephoneNumberMenuItems.isEmpty()) {
        if (m_menu)
            [m_menu insertItem:[NSMenuItem separatorItem] atIndex:0];
        else
            m_menu = adoptNS([[NSMenu alloc] init]);
        int itemPosition = 0;
        auto groupEntry = adoptNS([[NSMenuItem alloc] initWithTitle:menuItemTitleForTelephoneNumberGroup() action:nil keyEquivalent:@""]);
        [groupEntry setEnabled:NO];
        [m_menu insertItem:groupEntry.get() atIndex:itemPosition++];
        for (auto& menuItem : telephoneNumberMenuItems)
            [m_menu insertItem:menuItem.get() atIndex:itemPosition++];
    }

    // If there is no services menu, then the existing services on the system have changed, so refresh that list of services.
    // If <rdar://problem/17954709> is resolved then we can more accurately keep the list up to date without this call.
    if (!m_menu)
        ServicesController::singleton().refreshExistingServices();
}

void WebContextMenuProxyMac::showServicesMenu()
{
    setupServicesMenu();

    auto webView = m_webView.get();
    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setMenuProxy:this];
    [m_menu popUpMenuPositioningItem:nil atLocation:m_context.menuLocation() inView:webView.get()];
}

void WebContextMenuProxyMac::clearServicesMenu()
{
    [[WKSharingServicePickerDelegate sharedSharingServicePickerDelegate] setPicker:nullptr];
    m_menu = nullptr;
}

static void getStandardShareMenuItem(NSArray *items, void (^completionHandler)(NSMenuItem *))
{
#if HAVE(NSSHARINGSERVICEPICKER_ASYNC_MENUS)
    // FIXME (<rdar://problem/54551500>): Replace this with the async variant of +[NSMenuItem standardShareMenuItemForItems:] when it's available.
    auto sharingServicePicker = adoptNS([[NSSharingServicePicker alloc] initWithItems:items]);
    [sharingServicePicker setStyle:NSSharingServicePickerStyleMenu];
    [sharingServicePicker getMenuWithCompletion:^(NSMenu *shareMenu) {
        ASSERT(isMainThread());
        shareMenu.delegate = (id <NSMenuDelegate>)sharingServicePicker.get();
        auto shareMenuItem = adoptNS([[NSMenuItem alloc] initWithTitle:WEB_UI_STRING("Share", "Title for Share context menu item.") action:nil keyEquivalent:@""]);
        [shareMenuItem setRepresentedObject:sharingServicePicker.get()];
        [shareMenuItem setSubmenu:shareMenu];
        completionHandler(shareMenuItem.get());
    }];
#else
    completionHandler([NSMenuItem standardShareMenuItemForItems:items]);
#endif
}

void WebContextMenuProxyMac::getShareMenuItem(CompletionHandler<void(NSMenuItem *)>&& completionHandler)
{
    ASSERT(m_context.webHitTestResultData());
    auto hitTestData = m_context.webHitTestResultData().value();

    auto items = adoptNS([[NSMutableArray alloc] init]);

    if (!hitTestData.absoluteLinkURL.isEmpty()) {
        auto absoluteLinkURL = URL({ }, hitTestData.absoluteLinkURL);
        if (!absoluteLinkURL.isEmpty())
            [items addObject:(NSURL *)absoluteLinkURL];
    }

    if (hitTestData.isDownloadableMedia && !hitTestData.absoluteMediaURL.isEmpty()) {
        auto downloadableMediaURL = URL({ }, hitTestData.absoluteMediaURL);
        if (!downloadableMediaURL.isEmpty())
            [items addObject:(NSURL *)downloadableMediaURL];
    }

    if (hitTestData.imageSharedMemory && hitTestData.imageSize) {
        if (auto image = adoptNS([[NSImage alloc] initWithData:[NSData dataWithBytes:(unsigned char*)hitTestData.imageSharedMemory->data() length:hitTestData.imageSize]]))
            [items addObject:image.get()];
    }

    if (!m_context.selectedText().isEmpty())
        [items addObject:(NSString *)m_context.selectedText()];

    if (![items count]) {
        completionHandler(nil);
        return;
    }

    getStandardShareMenuItem(items.get(), makeBlockPtr([completionHandler = WTFMove(completionHandler), protectedThis = Ref { *this }, this](NSMenuItem *item) mutable {
        if (!item) {
            completionHandler(nil);
            return;
        }

        NSSharingServicePicker *sharingServicePicker = item.representedObject;
        WKSharingServicePickerDelegate *sharingServicePickerDelegate = WKSharingServicePickerDelegate.sharedSharingServicePickerDelegate;
        sharingServicePicker.delegate = sharingServicePickerDelegate;

        sharingServicePickerDelegate.filtersEditingServices = NO;
        sharingServicePickerDelegate.handlesEditingReplacement = NO;
        sharingServicePickerDelegate.menuProxy = this;

        // Setting the picker lets the delegate retain it to keep it alive, but this picker is kept alive by the menu item.
        sharingServicePickerDelegate.picker = nil;

        item.identifier = _WKMenuItemIdentifierShareMenu;

        completionHandler(item);
    }).get());
}
#endif

void WebContextMenuProxyMac::show()
{
#if ENABLE(SERVICE_CONTROLS)
    if (m_context.isServicesMenu()) {
        WebContextMenuProxy::useContextMenuItems({ });
        return;
    }
#endif

    WebContextMenuProxy::show();
}

static NSString *menuItemIdentifier(const WebCore::ContextMenuAction action)
{
    switch (action) {
    case ContextMenuItemTagCopy:
        return _WKMenuItemIdentifierCopy;

    case ContextMenuItemTagCopyImageToClipboard:
        return _WKMenuItemIdentifierCopyImage;

    case ContextMenuItemTagCopyLinkToClipboard:
        return _WKMenuItemIdentifierCopyLink;

    case ContextMenuItemTagCopyMediaLinkToClipboard:
        return _WKMenuItemIdentifierCopyMediaLink;

    case ContextMenuItemTagDownloadImageToDisk:
        return _WKMenuItemIdentifierDownloadImage;

    case ContextMenuItemTagDownloadLinkToDisk:
        return _WKMenuItemIdentifierDownloadLinkedFile;

    case ContextMenuItemTagDownloadMediaToDisk:
        return _WKMenuItemIdentifierDownloadMedia;

    case ContextMenuItemTagGoBack:
        return _WKMenuItemIdentifierGoBack;

    case ContextMenuItemTagGoForward:
        return _WKMenuItemIdentifierGoForward;

    case ContextMenuItemTagInspectElement:
        return _WKMenuItemIdentifierInspectElement;

    case ContextMenuItemTagLookUpInDictionary:
        return _WKMenuItemIdentifierLookUp;

    case ContextMenuItemTagAddHighlightToCurrentQuickNote:
        return _WKMenuItemIdentifierAddHighlightToCurrentQuickNote;
        
    case ContextMenuItemTagAddHighlightToNewQuickNote:
        return _WKMenuItemIdentifierAddHighlightToNewQuickNote;

    case ContextMenuItemTagOpenFrameInNewWindow:
        return _WKMenuItemIdentifierOpenFrameInNewWindow;

    case ContextMenuItemTagOpenImageInNewWindow:
        return _WKMenuItemIdentifierOpenImageInNewWindow;

    case ContextMenuItemTagOpenLink:
        return _WKMenuItemIdentifierOpenLink;

    case ContextMenuItemTagOpenLinkInNewWindow:
        return _WKMenuItemIdentifierOpenLinkInNewWindow;

    case ContextMenuItemTagOpenMediaInNewWindow:
        return _WKMenuItemIdentifierOpenMediaInNewWindow;

    case ContextMenuItemTagPaste:
        return _WKMenuItemIdentifierPaste;

    case ContextMenuItemTagReload:
        return _WKMenuItemIdentifierReload;

    case ContextMenuItemTagQuickLookImage:
        return _WKMenuItemIdentifierRevealImage;

    case ContextMenuItemTagSearchWeb:
        return _WKMenuItemIdentifierSearchWeb;

    case ContextMenuItemTagToggleMediaControls:
        return _WKMenuItemIdentifierShowHideMediaControls;

    case ContextMenuItemTagToggleVideoEnhancedFullscreen:
        return _WKMenuItemIdentifierToggleEnhancedFullScreen;

    case ContextMenuItemTagToggleVideoFullscreen:
        return _WKMenuItemIdentifierToggleFullScreen;

    case ContextMenuItemTagTranslate:
        return _WKMenuItemIdentifierTranslate;

    case ContextMenuItemTagShareMenu:
        return _WKMenuItemIdentifierShareMenu;

    case ContextMenuItemTagSpeechMenu:
        return _WKMenuItemIdentifierSpeechMenu;

    default:
        return nil;
    }
}

static RetainPtr<NSMenuItem> createMenuActionItem(const WebContextMenuItemData& item)
{
    auto type = item.type();
    ASSERT_UNUSED(type, type == WebCore::ActionType || type == WebCore::CheckableActionType);

    auto menuItem = adoptNS([[NSMenuItem alloc] initWithTitle:item.title() action:@selector(forwardContextMenuAction:) keyEquivalent:@""]);

    [menuItem setTag:item.action()];
    [menuItem setEnabled:item.enabled()];
    [menuItem setState:item.checked() ? NSControlStateValueOn : NSControlStateValueOff];
    [menuItem setIndentationLevel:item.indentationLevel()];
    [menuItem setTarget:[WKMenuTarget sharedMenuTarget]];
    [menuItem setIdentifier:menuItemIdentifier(item.action())];

    if (item.userData())
        [menuItem setRepresentedObject:adoptNS([[WKUserDataWrapper alloc] initWithUserData:item.userData()]).get()];

    return menuItem;
}

void WebContextMenuProxyMac::getContextMenuFromItems(const Vector<WebContextMenuItemData>& items, CompletionHandler<void(NSMenu *)>&& completionHandler)
{
    auto menu = adoptNS([[NSMenu alloc] initWithTitle:@""]);
    [menu setAutoenablesItems:NO];

    if (items.isEmpty()) {
        completionHandler(menu.get());
        return;
    }

    auto filteredItems = items;
    auto webView = m_webView.get();

    bool isPopover = webView.get().window._childWindowOrderingPriority == NSWindowChildOrderingPriorityPopover;
    bool isLookupDisabled = [NSUserDefaults.standardUserDefaults boolForKey:@"LULookupDisabled"];

    if (isLookupDisabled || isPopover) {
        filteredItems.removeAllMatching([] (auto& item) {
            return item.action() == WebCore::ContextMenuItemTagLookUpInDictionary;
        });
    }

    bool shouldUpdateQuickLookItemTitle = false;
    std::optional<WebContextMenuItemData> quickLookItemToInsertIfNeeded;

#if ENABLE(IMAGE_ANALYSIS)
    auto indexOfQuickLookItem = filteredItems.findIf([&] (auto& item) {
        return item.action() == WebCore::ContextMenuItemTagQuickLookImage;
    });

    if (indexOfQuickLookItem != notFound) {
        if (auto page = this->page(); page && page->preferences().preferInlineTextSelectionInImages()) {
            quickLookItemToInsertIfNeeded = filteredItems[indexOfQuickLookItem];
            filteredItems.remove(indexOfQuickLookItem);
        } else
            shouldUpdateQuickLookItemTitle = true;
    }
#endif // ENABLE(IMAGE_ANALYSIS)

#if HAVE(TRANSLATION_UI_SERVICES)
    if (!page()->canHandleContextMenuTranslation() || isPopover) {
        filteredItems.removeAllMatching([] (auto& item) {
            return item.action() == ContextMenuItemTagTranslate;
        });
    }
#endif

    ASSERT(m_context.webHitTestResultData());
    auto hitTestData = m_context.webHitTestResultData().value();
    
    auto imageURL = URL { URL { }, hitTestData.absoluteImageURL };
    auto imageBitmap = hitTestData.imageBitmap;

    auto sparseMenuItems = retainPtr([NSPointerArray strongObjectsPointerArray]);
    auto insertMenuItem = makeBlockPtr([protectedThis = Ref { *this }, weakPage = WeakPtr { page() }, imageURL = WTFMove(imageURL), imageBitmap = WTFMove(imageBitmap), shouldUpdateQuickLookItemTitle, quickLookItemToInsertIfNeeded = WTFMove(quickLookItemToInsertIfNeeded), completionHandler = WTFMove(completionHandler), itemsRemaining = filteredItems.size(), menu = WTFMove(menu), sparseMenuItems](NSMenuItem *item, NSUInteger index) mutable {
        ASSERT(index < [sparseMenuItems count]);
        ASSERT(![sparseMenuItems pointerAtIndex:index]);
        [sparseMenuItems replacePointerAtIndex:index withPointer:item];
        if (--itemsRemaining)
            return;

        [menu setItemArray:[sparseMenuItems allObjects]];

        RefPtr page { weakPage.get() };
        if (page && imageBitmap) {
#if ENABLE(IMAGE_ANALYSIS)
            protectedThis->insertOrUpdateQuickLookImageItem(imageURL, imageBitmap.releaseNonNull(), WTFMove(quickLookItemToInsertIfNeeded), shouldUpdateQuickLookItemTitle);
#else
            UNUSED_PARAM(quickLookItemToInsertIfNeeded);
            UNUSED_PARAM(shouldUpdateQuickLookItemTitle);
            UNUSED_PARAM(imageURL);
#endif
        }

        completionHandler(menu.get());
    });

    for (size_t i = 0; i < filteredItems.size(); ++i) {
        [sparseMenuItems addPointer:nullptr];
        getContextMenuItem(filteredItems[i], [insertMenuItem, i](NSMenuItem *menuItem) {
            insertMenuItem(menuItem, i);
        });
    }
}

#if ENABLE(IMAGE_ANALYSIS)

void WebContextMenuProxyMac::insertOrUpdateQuickLookImageItem(const URL& imageURL, Ref<ShareableBitmap>&& imageBitmap, std::optional<WebContextMenuItemData>&& quickLookItemToInsertIfNeeded, bool shouldUpdateQuickLookItemTitle)
{
    Ref page = *this->page();
    if (quickLookItemToInsertIfNeeded) {
        page->computeHasImageAnalysisResults(imageURL, imageBitmap.get(), ImageAnalysisType::VisualSearch, [weakThis = WeakPtr { *this }, quickLookItemToInsertIfNeeded = WTFMove(*quickLookItemToInsertIfNeeded)] (bool hasVisualSearchResults) mutable {
            if (RefPtr protectedThis = weakThis.get(); protectedThis && hasVisualSearchResults) {
                protectedThis->m_quickLookPreviewActivity = QuickLookPreviewActivity::VisualSearch;
                [protectedThis->m_menu addItem:NSMenuItem.separatorItem];
                [protectedThis->m_menu addItem:createMenuActionItem(quickLookItemToInsertIfNeeded).get()];
            }
        });
        return;
    }

    if (shouldUpdateQuickLookItemTitle) {
        page->computeHasImageAnalysisResults(imageURL, imageBitmap.get(), ImageAnalysisType::VisualSearch, [weakThis = WeakPtr { *this }, weakPage = WeakPtr { page }, imageURL, imageBitmap = WTFMove(imageBitmap)] (bool hasVisualSearchResults) mutable {
            RefPtr protectedThis { weakThis.get() };
            if (!protectedThis)
                return;

            RefPtr page { weakPage.get() };
            if (!page)
                return;

            if (hasVisualSearchResults) {
                protectedThis->m_quickLookPreviewActivity = QuickLookPreviewActivity::VisualSearch;
                protectedThis->updateQuickLookContextMenuItemTitle(contextMenuItemTagQuickLookImageForVisualSearch());
                return;
            }

            page->computeHasImageAnalysisResults(imageURL, imageBitmap.get(), ImageAnalysisType::Text, [weakThis = WTFMove(weakThis), weakPage] (bool hasText) mutable {
                RefPtr protectedThis { weakThis.get() };
                if (!protectedThis)
                    return;

                if (RefPtr page = weakPage.get(); page && hasText)
                    protectedThis->updateQuickLookContextMenuItemTitle(contextMenuItemTagQuickLookImageForTextSelection());
            });
        });
    }
}

void WebContextMenuProxyMac::updateQuickLookContextMenuItemTitle(const String& newTitle)
{
    for (NSInteger itemIndex = 0; itemIndex < [m_menu numberOfItems]; ++itemIndex) {
        auto item = [m_menu itemAtIndex:itemIndex];
        if (static_cast<ContextMenuAction>(item.tag) == ContextMenuItemTagQuickLookImage) {
            item.title = newTitle;
            break;
        }
    }
}

#endif // ENABLE(IMAGE_ANALYSIS)

void WebContextMenuProxyMac::getContextMenuItem(const WebContextMenuItemData& item, CompletionHandler<void(NSMenuItem *)>&& completionHandler)
{
#if ENABLE(SERVICE_CONTROLS)
    if (item.action() == ContextMenuItemTagShareMenu) {
        getShareMenuItem(WTFMove(completionHandler));
        return;
    }
#endif

    switch (item.type()) {
    case WebCore::ActionType:
    case WebCore::CheckableActionType:
        completionHandler(createMenuActionItem(item).get());
        return;

    case WebCore::SeparatorType:
        completionHandler(NSMenuItem.separatorItem);
        return;

    case WebCore::SubmenuType: {
        getContextMenuFromItems(item.submenu(), [action = item.action(), completionHandler = WTFMove(completionHandler), enabled = item.enabled(), title = item.title(), indentationLevel = item.indentationLevel()](NSMenu *menu) mutable {
            auto menuItem = adoptNS([[NSMenuItem alloc] initWithTitle:title action:nullptr keyEquivalent:@""]);
            [menuItem setEnabled:enabled];
            [menuItem setIndentationLevel:indentationLevel];
            [menuItem setSubmenu:menu];
            [menuItem setIdentifier:menuItemIdentifier(action)];
            completionHandler(menuItem.get());
        });
        return;
    }
    }
}

void WebContextMenuProxyMac::showContextMenuWithItems(Vector<Ref<WebContextMenuItem>>&& items)
{
#if ENABLE(SERVICE_CONTROLS)
    if (m_context.isServicesMenu()) {
        ASSERT(items.isEmpty());
        showServicesMenu();
        return;
    }
#endif

    if (page()->contextMenuClient().canShowContextMenu()) {
        page()->contextMenuClient().showContextMenu(*page(), m_context.menuLocation(), items);
        return;
    }

    ASSERT(items.isEmpty());
    if (!m_menu)
        return;

    auto webView = m_webView.get();
    NSPoint menuLocation = [webView convertPoint:m_context.menuLocation() toView:nil];
    NSEvent *event = [NSEvent mouseEventWithType:NSEventTypeRightMouseUp location:menuLocation modifierFlags:0 timestamp:0 windowNumber:[webView window].windowNumber context:nil eventNumber:0 clickCount:0 pressure:0];
    [NSMenu popUpContextMenu:m_menu.get() withEvent:event forView:webView.get()];
}

void WebContextMenuProxyMac::useContextMenuItems(Vector<Ref<WebContextMenuItem>>&& items)
{
    if (items.isEmpty() || !page() || page()->contextMenuClient().canShowContextMenu()) {
        WebContextMenuProxy::useContextMenuItems(WTFMove(items));
        return;
    }

    auto data = WTF::map(items, [](auto& item) {
        return item->data();
    });

    getContextMenuFromItems(data, [this, protectedThis = Ref { *this }](NSMenu *menu) mutable {
        if (!page()) {
            WebContextMenuProxy::useContextMenuItems({ });
            return;
        }

        [[WKMenuTarget sharedMenuTarget] setMenuProxy:this];

        auto menuFromProposedMenu = [this, protectedThis = WTFMove(protectedThis)] (RetainPtr<NSMenu>&& menu) {
            m_menuDelegate = adoptNS([[WKMenuDelegate alloc] initWithMenuProxy:*this]);

            m_menu = WTFMove(menu);
            [m_menu setDelegate:m_menuDelegate.get()];

            WebContextMenuProxy::useContextMenuItems({ });
        };

        if (m_context.type() != ContextMenuContext::Type::ContextMenu) {
            menuFromProposedMenu(menu);
            return;
        }
        
        ASSERT(m_context.webHitTestResultData());
        page()->contextMenuClient().menuFromProposedMenu(*page(), menu, m_context.webHitTestResultData().value(), m_userData.object(), WTFMove(menuFromProposedMenu));
    });
}

NSWindow *WebContextMenuProxyMac::window() const
{
    return [m_webView window];
}

NSMenu *WebContextMenuProxyMac::platformMenu() const
{
    return m_menu.get();
}

static NSDictionary *contentsOfContextMenuItem(NSMenuItem *item)
{
    NSMutableDictionary* result = NSMutableDictionary.dictionary;

    if (item.title.length)
        result[@"title"] = item.title;

    if (item.isSeparatorItem)
        result[@"separator"] = @YES;
    else if (!item.enabled)
        result[@"enabled"] = @NO;

    if (NSInteger indentationLevel = item.indentationLevel)
        result[@"indentationLevel"] = [NSNumber numberWithInteger:indentationLevel];

    if (item.state == NSControlStateValueOn)
        result[@"checked"] = @YES;

    if (NSArray<NSMenuItem *> *submenuItems = item.submenu.itemArray) {
        NSMutableArray *children = [NSMutableArray arrayWithCapacity:submenuItems.count];
        for (NSMenuItem *submenuItem : submenuItems)
            [children addObject:contentsOfContextMenuItem(submenuItem)];
        result[@"children"] = children;
    }

    return result;
}

NSArray *WebContextMenuProxyMac::platformData() const
{
    NSMutableArray *result = NSMutableArray.array;

    if (NSArray<NSMenuItem *> *submenuItems = [m_menu itemArray]) {
        NSMutableArray *children = [NSMutableArray arrayWithCapacity:submenuItems.count];
        for (NSMenuItem *submenuItem : submenuItems)
            [children addObject:contentsOfContextMenuItem(submenuItem)];
        [result addObject:@{ @"children": children }];
    }

    return result;
}

} // namespace WebKit

#endif // PLATFORM(MAC)
