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

#import "PageClientImpl.h"
#import "WebContextMenuItemData.h"
#import "WKView.h"

#import <WebCore/IntRect.h>
#import <WebKitSystemInterface.h>

using namespace WebCore;

@interface WebUserDataWrapper : NSObject {
    RefPtr<WebKit::APIObject> _webUserData;
}
- (id)initWithUserData:(WebKit::APIObject*)userData;
- (WebKit::APIObject*)userData;
@end

@implementation WebUserDataWrapper

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

- (WebKit::APIObject*)userData
{
    return _webUserData.get();
}

@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
{
    WebKit::WebContextMenuItemData item(ActionType, static_cast<ContextMenuAction>([sender tag]), [sender title], [sender isEnabled], [sender state] == NSOnState);
    
    if (id representedObject = [sender representedObject]) {
        ASSERT([representedObject isKindOfClass:[WebUserDataWrapper class]]);
        item.setUserData([static_cast<WebUserDataWrapper *>(representedObject) userData]);
    }
            
    _menuProxy->contextMenuItemSelected(item);
}

@end

namespace WebKit {

WebContextMenuProxyMac::WebContextMenuProxyMac(WKView* webView, WebPageProxy* page)
    : m_webView(webView)
    , m_page(page)
{
}

WebContextMenuProxyMac::~WebContextMenuProxyMac()
{
    if (m_popup)
        [m_popup.get() setControlView:nil];
}

void WebContextMenuProxyMac::contextMenuItemSelected(const WebContextMenuItemData& item)
{
    m_page->contextMenuItemSelected(item);
}

static void populateNSMenu(NSMenu* menu, const Vector<RetainPtr<NSMenuItem> >& menuItemVector)
{
    for (unsigned i = 0; i < menuItemVector.size(); ++i) {
        NSInteger oldState = [menuItemVector[i].get() state];
        [menu addItem:menuItemVector[i].get()];
        [menuItemVector[i].get() setState:oldState];
    }
}

static Vector<RetainPtr<NSMenuItem> > nsMenuItemVector(const Vector<WebContextMenuItemData>& items)
{
    Vector<RetainPtr<NSMenuItem> > result;

    unsigned size = items.size();
    result.reserveCapacity(size);
    for (unsigned i = 0; i < size; i++) {
        switch (items[i].type()) {
        case ActionType:
        case CheckableActionType: {
            NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:nsStringFromWebCoreString(items[i].title()) action:@selector(forwardContextMenuAction:) keyEquivalent:@""];
            [menuItem setTag:items[i].action()];
            [menuItem setEnabled:items[i].enabled()];
            [menuItem setState:items[i].checked() ? NSOnState : NSOffState];
                        
            if (items[i].userData()) {
                WebUserDataWrapper *wrapper = [[WebUserDataWrapper alloc] initWithUserData:items[i].userData()];
                [menuItem setRepresentedObject:wrapper];
                [wrapper release];
            }

            result.append(RetainPtr<NSMenuItem>(AdoptNS, menuItem));
            break;
        }
        case SeparatorType:
            result.append([NSMenuItem separatorItem]);
            break;
        case SubmenuType: {
            NSMenu* menu = [[NSMenu alloc] initWithTitle:nsStringFromWebCoreString(items[i].title())];
            [menu setAutoenablesItems:NO];
            populateNSMenu(menu, nsMenuItemVector(items[i].submenu()));
                
            NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:nsStringFromWebCoreString(items[i].title()) action:@selector(forwardContextMenuAction:) keyEquivalent:@""];
            [menuItem setEnabled:items[i].enabled()];
            [menuItem setSubmenu:menu];
            [menu release];

            result.append(RetainPtr<NSMenuItem>(AdoptNS, menuItem));
            
            break;
        }
        default:
            ASSERT_NOT_REACHED();
        }
    }

    WKMenuTarget* target = [WKMenuTarget sharedMenuTarget];
    for (unsigned i = 0; i < size; ++i)
        [result[i].get() setTarget:target];
    
    return result;
}

void WebContextMenuProxyMac::populate(const Vector<WebContextMenuItemData>& items)
{
    if (m_popup)
        [m_popup.get() removeAllItems];
    else {
        m_popup.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
        [m_popup.get() setUsesItemFromMenu:NO];
        [m_popup.get() setAutoenablesItems:NO];
    }

    NSMenu* menu = [m_popup.get() menu];
    populateNSMenu(menu, nsMenuItemVector(items));
}

void WebContextMenuProxyMac::showContextMenu(const IntPoint& menuLocation, const Vector<WebContextMenuItemData>& items)
{
    if (items.isEmpty())
        return;
    
    populate(items);
    [[WKMenuTarget sharedMenuTarget] setMenuProxy:this];
    
    NSRect menuRect = NSMakeRect(menuLocation.x(), menuLocation.y(), 0, 0);
    
    [m_popup.get() attachPopUpWithFrame:menuRect inView:m_webView];

    NSMenu* menu = [m_popup.get() menu];

    // These values were borrowed from AppKit to match their placement of the menu.
    NSRect titleFrame = [m_popup.get()  titleRectForBounds:menuRect];
    if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0)
        titleFrame = menuRect;
    float vertOffset = roundf((NSMaxY(menuRect) - NSMaxY(titleFrame)) + NSHeight(titleFrame));
    NSPoint location = NSMakePoint(NSMinX(menuRect), NSMaxY(menuRect) - vertOffset);

    location = [m_webView convertPoint:location toView:nil];
    location = [m_webView.window convertBaseToScreen:location];
 
    WKPopupContextMenu(menu, location);

    [m_popup.get() dismissPopUp];
}

void WebContextMenuProxyMac::hideContextMenu()
{
    [m_popup.get() dismissPopUp];
}

} // namespace WebKit
