/*
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#import <JavaNativeFoundation/JavaNativeFoundation.h>
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>


#import "CMenu.h"
#import "CMenuBar.h"
#import "ThreadUtilities.h"

#import "sun_lwawt_macosx_CMenu.h"

@implementation CMenu

- (id)initWithPeer:(jobject)peer {
AWT_ASSERT_APPKIT_THREAD;
    // Create the new NSMenu
    self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]];
    if (self) {
        fMenu = [NSMenu javaMenuWithTitle:@""];
        [fMenu retain];
        [fMenu setAutoenablesItems:NO];
    }
    return self;
}

- (void)dealloc {
    [fMenu release];
    fMenu = nil;
    [super dealloc];
}
//- (void)finalize { [super finalize]; }

- (void)addJavaSubmenu:(CMenu *)submenu {
    [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES];
}

- (void)addJavaMenuItem:(CMenuItem *)theMenuItem {
    [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:theMenuItem waitUntilDone:YES];
}

- (void)addNativeItem_OnAppKitThread:(CMenuItem *)itemModified {
AWT_ASSERT_APPKIT_THREAD;
    [itemModified addNSMenuItemToMenu:[self menu]];
}

- (void)setJavaMenuTitle:(NSString *)title {

    if (title) {
        [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) on:self withObject:title waitUntilDone:YES];
    }
}

- (void)setNativeMenuTitle_OnAppKitThread:(NSString *)title {
AWT_ASSERT_APPKIT_THREAD;

    [fMenu setTitle:title];
    // If we are a submenu we need to set our name in the parent menu's menu item.
    NSMenu *parent = [fMenu supermenu];
    if (parent) {
        NSInteger index = [parent indexOfItemWithSubmenu:fMenu];
        NSMenuItem *menuItem = [parent itemAtIndex:index];
        [menuItem setTitle:title];
    }
}

- (void)addSeparator {
    // Nothing calls this, which is good because we need a CMenuItem here.
}

- (void)deleteJavaItem:(jint)index {

    [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES];
}

- (void)deleteNativeJavaItem_OnAppKitThread:(NSNumber *)number {
AWT_ASSERT_APPKIT_THREAD;

    int n = [number intValue];
    if (n < [[self menu] numberOfItems]) {
        [[self menu] removeItemAtIndex:n];
    }
}

- (void)addNSMenuItemToMenu:(NSMenu *)inMenu {
    if (fMenuItem == nil) return;
    [fMenuItem setSubmenu:fMenu];
    [inMenu addItem:fMenuItem];
}

- (NSMenu *)menu {
    return [[fMenu retain] autorelease];
}

- (void)setNativeEnabled_OnAppKitThread:(NSNumber *)boolNumber {
AWT_ASSERT_APPKIT_THREAD;

    @synchronized(self) {
        fIsEnabled = [boolNumber boolValue];

        NSMenu* supermenu = [fMenu supermenu];
        [[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:fMenu]] setEnabled:fIsEnabled];
    }
}

- (NSString *)description {
    return [NSString stringWithFormat:@"CMenu[ %@ ]", fMenu];
}

@end

CMenu * createCMenu (jobject cPeerObjGlobal) {

    CMenu *aCMenu = nil;

    // We use an array here only to be able to get a return value
    NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];

    [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES];

    aCMenu = (CMenu *)[args objectAtIndex: 0];

    if (aCMenu == nil) {
        return 0L;
    }

    return aCMenu;

}

/*
 * Class:     sun_lwawt_macosx_CMenu
 * Method:    nativeCreateSubMenu
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL
Java_sun_lwawt_macosx_CMenu_nativeCreateSubMenu
(JNIEnv *env, jobject peer, jlong parentMenu)
{
    CMenu *aCMenu = nil;
JNF_COCOA_ENTER(env);

    jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);

    aCMenu = createCMenu (cPeerObjGlobal);

    // Add it to the parent menu
    [((CMenu *)jlong_to_ptr(parentMenu)) addJavaSubmenu: aCMenu];
    if (aCMenu) {
        CFRetain(aCMenu); // GC
        [aCMenu release];
    }

JNF_COCOA_EXIT(env);

    return ptr_to_jlong(aCMenu);
}



/*
 * Class:     sun_lwawt_macosx_CMenu
 * Method:    nativeCreateMenu
 * Signature: (JZ)J
 */
JNIEXPORT jlong JNICALL
Java_sun_lwawt_macosx_CMenu_nativeCreateMenu
(JNIEnv *env, jobject peer,
        jlong parentMenuBar, jboolean isHelpMenu, jint insertLocation)
{
    CMenu *aCMenu = nil;
    CMenuBar *parent = (CMenuBar *)jlong_to_ptr(parentMenuBar);
JNF_COCOA_ENTER(env);

    jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);

    aCMenu = createCMenu (cPeerObjGlobal);

    // Add it to the menu bar.
    [parent javaAddMenu:aCMenu atIndex:insertLocation];

    // If the menu is already the help menu (because we are creating an entire
    // menu bar) we need to note that now, because we can't rely on
    // setHelpMenu() being called again.
    if (isHelpMenu == JNI_TRUE) {
        [parent javaSetHelpMenu: aCMenu];
    }

    if (aCMenu) {
        CFRetain(aCMenu); // GC
        [aCMenu release];
    }
JNF_COCOA_EXIT(env);
    return ptr_to_jlong(aCMenu);
}


/*
 * Class:     sun_lwawt_macosx_CMenu
 * Method:    nativeSetMenuTitle
 * Signature: (JLjava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CMenu_nativeSetMenuTitle
(JNIEnv *env, jobject peer, jlong menuObject, jstring label)
{
JNF_COCOA_ENTER(env);
    // Set the menu's title.
    [((CMenu *)jlong_to_ptr(menuObject)) setJavaMenuTitle:JNFJavaToNSString(env, label)];
JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_CMenu
 * Method:    nativeAddSeparator
 * Signature: (J)V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CMenu_nativeAddSeparator
(JNIEnv *env, jobject peer, jlong menuObject)
{
JNF_COCOA_ENTER(env);
    // Add a separator item.
    [((CMenu *)jlong_to_ptr(menuObject))addSeparator];
JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_CMenu
 * Method:    nativeDeleteItem
 * Signature: (JI)V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CMenu_nativeDeleteItem
(JNIEnv *env, jobject peer, jlong menuObject, jint index)
{
JNF_COCOA_ENTER(env);
    // Remove the specified item.
    [((CMenu *)jlong_to_ptr(menuObject)) deleteJavaItem: index];
JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_CMenu
 * Method:    nativeGetNSMenu
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL
Java_sun_lwawt_macosx_CMenu_nativeGetNSMenu
(JNIEnv *env, jobject peer, jlong menuObject)
{
    NSMenu* nsMenu = NULL;

JNF_COCOA_ENTER(env);
    nsMenu = [((CMenu *)jlong_to_ptr(menuObject)) menu];
JNF_COCOA_EXIT(env);

    // Strong retain this menu; it'll get released in Java_apple_laf_ScreenMenu_addMenuListeners
    if (nsMenu) {
        CFRetain(nsMenu); // GC
    }

    return ptr_to_jlong(nsMenu);
}
