/*
 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#import "config.h"
#import "PopupMenu.h"

#import "AXObjectCache.h"
#import "Chrome.h"
#import "ChromeClient.h"
#import "EventHandler.h"
#import "Frame.h"
#import "FrameView.h"
#import "HTMLNames.h"
#import "HTMLOptGroupElement.h"
#import "HTMLOptionElement.h"
#import "HTMLSelectElement.h"
#import "Page.h"
#import "SimpleFontData.h"
#import "WebCoreSystemInterface.h"

namespace WebCore {

using namespace HTMLNames;

PopupMenu::PopupMenu(PopupMenuClient* client)
    : m_popupClient(client)
{
}

PopupMenu::~PopupMenu()
{
    if (m_popup)
        [m_popup.get() setControlView:nil];
}

void PopupMenu::clear()
{
    if (m_popup)
        [m_popup.get() removeAllItems];
}

void PopupMenu::populate()
{
    if (m_popup)
        clear();
    else {
        m_popup = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:!client()->shouldPopOver()];
        [m_popup.get() release]; // release here since the RetainPtr has retained the object already
        [m_popup.get() setUsesItemFromMenu:NO];
        [m_popup.get() setAutoenablesItems:NO];
    }

    BOOL messagesEnabled = [[m_popup.get() menu] menuChangedMessagesEnabled];
    [[m_popup.get() menu] setMenuChangedMessagesEnabled:NO];
    
    // For pullDown menus the first item is hidden.
    if (!client()->shouldPopOver())
        [m_popup.get() addItemWithTitle:@""];

    ASSERT(client());
    int size = client()->listSize();

    for (int i = 0; i < size; i++) {
        if (client()->itemIsSeparator(i))
            [[m_popup.get() menu] addItem:[NSMenuItem separatorItem]];
        else {
            PopupMenuStyle style = client()->itemStyle(i);
            NSMutableDictionary* attributes = [[NSMutableDictionary alloc] init];
            if (style.font() != Font()) {
                NSFont *font = style.font().primaryFont()->getNSFont();
                if (!font) {
                    CGFloat size = style.font().primaryFont()->platformData().size();
                    font = style.font().weight() < FontWeightBold ? [NSFont systemFontOfSize:size] : [NSFont boldSystemFontOfSize:size];
                }
                [attributes setObject:font forKey:NSFontAttributeName];
            }
            // FIXME: Add support for styling the foreground and background colors.
            // FIXME: Find a way to customize text color when an item is highlighted.
            NSAttributedString* string = [[NSAttributedString alloc] initWithString:client()->itemText(i) attributes:attributes];
            [attributes release];

            [m_popup.get() addItemWithTitle:@""];
            NSMenuItem* menuItem = [m_popup.get() lastItem];
            [menuItem setAttributedTitle:string];
            [menuItem setEnabled:client()->itemIsEnabled(i)];
            [menuItem setToolTip:client()->itemToolTip(i)];
            [string release];
            
            // Allow the accessible text of the item to be overriden if necessary.
            if (AXObjectCache::accessibilityEnabled()) {
                NSString *accessibilityOverride = client()->itemAccessibilityText(i);
                if ([accessibilityOverride length])
                    [menuItem accessibilitySetOverrideValue:accessibilityOverride forAttribute:NSAccessibilityDescriptionAttribute];
            }
        }
    }

    [[m_popup.get() menu] setMenuChangedMessagesEnabled:messagesEnabled];
}

#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE)

void PopupMenu::show(const IntRect& r, FrameView* v, int index)
{
    populate();
    int numItems = [m_popup.get() numberOfItems];
    if (numItems <= 0) {
        if (client())
            client()->popupDidHide();
        return;
    }
    ASSERT(numItems > index);

    // Workaround for crazy bug where a selected index of -1 for a menu with only 1 item will cause a blank menu.
    if (index == -1 && numItems == 2 && !client()->shouldPopOver() && ![[m_popup.get() itemAtIndex:1] isEnabled])
        index = 0;

    NSView* view = v->documentView();

    [m_popup.get() attachPopUpWithFrame:r inView:view];
    [m_popup.get() selectItemAtIndex:index];

    NSMenu* menu = [m_popup.get() menu];
    
    NSPoint location;
    NSFont* font = client()->menuStyle().font().primaryFont()->getNSFont();

    // These values were borrowed from AppKit to match their placement of the menu.
    const int popOverHorizontalAdjust = -10;
    const int popUnderHorizontalAdjust = 6;
    const int popUnderVerticalAdjust = 6;
    if (client()->shouldPopOver()) {
        NSRect titleFrame = [m_popup.get() titleRectForBounds:r];
        if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0)
            titleFrame = r;
        float vertOffset = roundf((NSMaxY(r) - NSMaxY(titleFrame)) + NSHeight(titleFrame));
        // Adjust for fonts other than the system font.
        NSFont* defaultFont = [NSFont systemFontOfSize:[font pointSize]];
        vertOffset += [font descender] - [defaultFont descender];
        vertOffset = fminf(NSHeight(r), vertOffset);
    
        location = NSMakePoint(NSMinX(r) + popOverHorizontalAdjust, NSMaxY(r) - vertOffset);
    } else
        location = NSMakePoint(NSMinX(r) + popUnderHorizontalAdjust, NSMaxY(r) + popUnderVerticalAdjust);    

    // Save the current event that triggered the popup, so we can clean up our event
    // state after the NSMenu goes away.
    RefPtr<Frame> frame = v->frame();
    NSEvent* event = [frame->eventHandler()->currentNSEvent() retain];
    
    RefPtr<PopupMenu> protector(this);

    RetainPtr<NSView> dummyView(AdoptNS, [[NSView alloc] initWithFrame:r]);
    [view addSubview:dummyView.get()];
    location = [dummyView.get() convertPoint:location fromView:view];
    
    if (Page* page = frame->page())
        page->chrome()->client()->willPopUpMenu(menu);
    wkPopupMenu(menu, location, roundf(NSWidth(r)), dummyView.get(), index, font);

    [m_popup.get() dismissPopUp];
    [dummyView.get() removeFromSuperview];

    if (client()) {
        int newIndex = [m_popup.get() indexOfSelectedItem];
        client()->popupDidHide();

        // Adjust newIndex for hidden first item.
        if (!client()->shouldPopOver())
            newIndex--;

        if (index != newIndex && newIndex >= 0)
            client()->valueChanged(newIndex);

        // Give the frame a chance to fix up its event state, since the popup eats all the
        // events during tracking.
        frame->eventHandler()->sendFakeEventsAfterWidgetTracking(event);
    }

    [event release];
}

#else

void PopupMenu::show(const IntRect&, FrameView*, int)
{
}

#endif

void PopupMenu::hide()
{
    [m_popup.get() dismissPopUp];
}
    
void PopupMenu::updateFromElement()
{
}

bool PopupMenu::itemWritingDirectionIsNatural()
{
    return true;
}

}
