/*
 * 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 <AppKit/AppKit.h>
#import <JavaNativeFoundation/JavaNativeFoundation.h>
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>


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

#import "sun_lwawt_macosx_CMenuBar.h"

__attribute__((visibility("default")))
NSString *CMenuBarDidReuseItemNotification =
    @"CMenuBarDidReuseItemNotification";

static CMenuBar *sActiveMenuBar = nil;
static NSMenu *sDefaultHelpMenu = nil;
static BOOL sSetupHelpMenu = NO;

@interface CMenuBar (CMenuBar_Private)
+ (void) addDefaultHelpMenu;
@end

@implementation CMenuBar

+ (void)clearMenuBarExcludingAppleMenu_OnAppKitThread:(BOOL) excludingAppleMenu {
    AWT_ASSERT_APPKIT_THREAD;
    // Remove all Java menus from the main bar.
    NSMenu *theMainMenu = [NSApp mainMenu];
    NSUInteger i, menuCount = [theMainMenu numberOfItems];

    for (i = menuCount; i > 1; i--) {
        NSUInteger index = i-1;

        NSMenuItem *currItem = [theMainMenu itemAtIndex:index];
        NSMenu *currMenu = [currItem submenu];

        if (excludingAppleMenu && ![currMenu isJavaMenu]) {
            continue;
        }
        [currItem setSubmenu:nil];
        [theMainMenu removeItemAtIndex:index];
    }

    [CMenuBar addDefaultHelpMenu];
}

+ (BOOL) isActiveMenuBar:(CMenuBar *)inMenuBar {
    return (sActiveMenuBar == inMenuBar);
}

- (id) initWithPeer:(jobject)peer {
    AWT_ASSERT_APPKIT_THREAD;
    self = [super initWithPeer: peer];
    if (self) {
        fMenuList = [[NSMutableArray alloc] init];
    }
    return self;
}

-(void) dealloc {
    [fMenuList release];
    fMenuList = nil;

    [fHelpMenu release];
    fHelpMenu = nil;

    [super dealloc];
}

+ (void) activate:(CMenuBar *)menubar modallyDisabled:(BOOL)modallyDisabled {
    AWT_ASSERT_APPKIT_THREAD;

    if (!menubar) {
        [CMenuBar clearMenuBarExcludingAppleMenu_OnAppKitThread:YES];
        return;
    }

    @synchronized([CMenuBar class]) {
        sActiveMenuBar = menubar;
    }

    @synchronized(menubar) {
        menubar->fModallyDisabled = modallyDisabled;
    }

    NSUInteger i = 0, newMenuListSize = [menubar->fMenuList count];

    NSMenu *theMainMenu = [NSApp mainMenu];
    NSUInteger menuIndex, menuCount = [theMainMenu numberOfItems];

    NSUInteger cmenuIndex = 0, cmenuCount = newMenuListSize;
    NSMutableArray *removedMenuArray = [NSMutableArray array];

    for (menuIndex = 0; menuIndex < menuCount; menuIndex++) {
        NSMenuItem *currItem = [theMainMenu itemAtIndex:menuIndex];
        NSMenu *currMenu = [currItem submenu];

        if ([currMenu isJavaMenu]) {
            // Ready to replace, find next candidate
            CMenu *newMenu = nil;
            if (cmenuIndex < cmenuCount) {
                newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:cmenuIndex];
                if (newMenu == menubar->fHelpMenu) {
                    cmenuIndex++;
                    if (cmenuIndex < cmenuCount) {
                        newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:cmenuIndex];
                    }
                }
            }
            if (newMenu) {
                NSMenu *menuToAdd = [newMenu menu];
                if ([theMainMenu indexOfItemWithSubmenu:menuToAdd] == -1) {
                    [[NSNotificationCenter defaultCenter] postNotificationName:CMenuBarDidReuseItemNotification object:theMainMenu];

                    [currItem setSubmenu:menuToAdd];
                    [currItem setTitle:[menuToAdd title]];
                    cmenuIndex++;
                }

                BOOL newEnabledState = [newMenu isEnabled] && !menubar->fModallyDisabled;
                [currItem setEnabled:newEnabledState];
            } else {
                [removedMenuArray addObject:[NSNumber numberWithInteger:menuIndex]];
            }
        }
    }

    // Clean up extra items
    NSUInteger removedIndex, removedCount = [removedMenuArray count];
    for (removedIndex=removedCount; removedIndex > 0; removedIndex--) {
        NSUInteger index = [[removedMenuArray objectAtIndex:(removedIndex-1)] integerValue];
        NSMenuItem *currItem = [theMainMenu itemAtIndex:index];
        [currItem setSubmenu:nil];
        [theMainMenu removeItemAtIndex:index];
    }

    i = cmenuIndex;

    // Add all of the menus in the menu list.
    for (; i < newMenuListSize; i++) {
        CMenu *newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:i];

        if (newMenu != menubar->fHelpMenu) {
            NSArray *args = [NSArray arrayWithObjects:newMenu, [NSNumber numberWithInt:-1], nil];
            [menubar nativeAddMenuAtIndex_OnAppKitThread:args];
        }
    }

    // Add the help menu last.
    if (menubar->fHelpMenu) {
        NSArray *args = [NSArray arrayWithObjects:menubar->fHelpMenu, [NSNumber numberWithInt:-1], nil];
        [menubar nativeAddMenuAtIndex_OnAppKitThread:args];
    } else {
        [CMenuBar addDefaultHelpMenu];
    }
}

-(void) deactivate {
    AWT_ASSERT_APPKIT_THREAD;

    @synchronized([CMenuBar class]) {
        sActiveMenuBar = nil;
    }

    @synchronized(self) {
        fModallyDisabled = NO;
    }
}

-(void) javaAddMenu: (CMenu *)theMenu {
    @synchronized(self) {
        [fMenuList addObject: theMenu];
    }

    if (self == sActiveMenuBar) {
        NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:-1], nil];
        [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];
        [args release];
    }
}

// This method is a special case for use by the screen menu bar.
// See ScreenMenuBar.java -- used to implement setVisible(boolean) by
// removing or adding the menu from the current menu bar's list.
-(void) javaAddMenu: (CMenu *)theMenu atIndex:(jint)index {
    @synchronized(self) {
        if (index == -1){
            [fMenuList addObject:theMenu];
        }else{
            [fMenuList insertObject:theMenu atIndex:index];
        }
    }

    if (self == sActiveMenuBar) {
        NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:index], nil];
        [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];
        [args release];
    }
}

- (NSInteger) javaIndexToNSMenuIndex_OnAppKitThread:(jint)javaIndex {
    AWT_ASSERT_APPKIT_THREAD;
    NSInteger returnValue = -1;
    NSMenu *theMainMenu = [NSApp mainMenu];

    if (javaIndex == -1) {
        if (fHelpMenu) {
            returnValue = [theMainMenu indexOfItemWithSubmenu:[fHelpMenu menu]];
        }
    } else {
        CMenu *requestedMenu = [fMenuList objectAtIndex:javaIndex];

        if (requestedMenu == fHelpMenu) {
            returnValue = [theMainMenu indexOfItemWithSubmenu:[fHelpMenu menu]];
        } else {
            NSUInteger i, menuCount = [theMainMenu numberOfItems];
            jint currJavaMenuIndex = 0;
            for (i = 0; i < menuCount; i++) {
                NSMenuItem *currItem = [theMainMenu itemAtIndex:i];
                NSMenu *currMenu = [currItem submenu];

                if ([currMenu isJavaMenu]) {
                    if (javaIndex == currJavaMenuIndex) {
                        returnValue = i;
                        break;
                    }

                    currJavaMenuIndex++;
                }
            }
        }
    }

    return returnValue;
}

- (void) nativeAddMenuAtIndex_OnAppKitThread:(NSArray *)args {
    AWT_ASSERT_APPKIT_THREAD;
    CMenu *theNewMenu = (CMenu*)[args objectAtIndex:0];
    jint index = [(NSNumber*)[args objectAtIndex:1] intValue];
    NSApplication *theApp = [NSApplication sharedApplication];
    NSMenu *theMainMenu = [theApp mainMenu];
    NSMenu *menuToAdd = [theNewMenu menu];

    if ([theMainMenu indexOfItemWithSubmenu:menuToAdd] == -1) {
        NSMenuItem *newItem = [[NSMenuItem alloc] init];
        [newItem setSubmenu:[theNewMenu menu]];
        [newItem setTitle:[[theNewMenu menu] title]];

        NSInteger nsMenuIndex = [self javaIndexToNSMenuIndex_OnAppKitThread:index];

        if (nsMenuIndex == -1) {
            [theMainMenu addItem:newItem];
        } else {
            [theMainMenu insertItem:newItem atIndex:nsMenuIndex];
        }

        BOOL newEnabledState = [theNewMenu isEnabled] && !fModallyDisabled;
        [newItem setEnabled:newEnabledState];
        [newItem release];
    }
}

- (void) javaDeleteMenu: (jint)index {
    if (self == sActiveMenuBar) {
        [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES];
    }

    @synchronized(self) {
        CMenu *menuToRemove = [fMenuList objectAtIndex:index];

        if (menuToRemove == fHelpMenu) {
            [fHelpMenu release];
            fHelpMenu = nil;
        }

        [fMenuList removeObjectAtIndex:index];
    }
}

- (void) nativeDeleteMenu_OnAppKitThread:(id)indexObj {
    AWT_ASSERT_APPKIT_THREAD;
    NSApplication *theApp = [NSApplication sharedApplication];
    NSMenu *theMainMenu = [theApp mainMenu];
    jint menuToRemove = [(NSNumber *)indexObj intValue];
    NSInteger nsMenuToRemove = [self javaIndexToNSMenuIndex_OnAppKitThread:menuToRemove];

    if (nsMenuToRemove != -1) {
        [theMainMenu removeItemAtIndex:nsMenuToRemove];
    }
}

- (void) javaSetHelpMenu:(CMenu *)theMenu {
    @synchronized(self) {
        [theMenu retain];
        [fHelpMenu release];
        fHelpMenu = theMenu;
    }
}

+ (void) addDefaultHelpMenu {
    AWT_ASSERT_APPKIT_THREAD;

    // Look for a help book tag. If it's there, add the help menu.
    @synchronized ([CMenuBar class]) {
        if (!sSetupHelpMenu) {
            if (sDefaultHelpMenu == nil) {
                // If we are embedded, don't make a help menu.
                // TODO(cpc): we don't have NSApplicationAWT yet...
                //if (![NSApp isKindOfClass:[NSApplicationAWT class]]) {
                //    sSetupHelpMenu = YES;
                //    return;
                //}

                // If the developer specified a NIB, don't make a help menu.
                // TODO(cpc): usingDefaultNib only defined on NSApplicationAWT
                //if (![NSApp usingDefaultNib]) {
                //    sSetupHelpMenu = YES;
                //    return;
                //}

            // TODO: not implemented
            }

            sSetupHelpMenu = YES;
        }
    }

    if (sDefaultHelpMenu) {
        NSMenu *theMainMenu = [NSApp mainMenu];

        if ([theMainMenu indexOfItemWithSubmenu:sDefaultHelpMenu] == -1) {
            // Since we're re-using this NSMenu, we need to clear its parent before
            // adding it to a new menu item, or else AppKit will complain.
            [sDefaultHelpMenu setSupermenu:nil];

            // Add the help menu to the main menu.
            NSMenuItem *newItem = [[NSMenuItem alloc] init];
            [newItem setSubmenu:sDefaultHelpMenu];
            [newItem setTitle:[sDefaultHelpMenu title]];
            [theMainMenu addItem:newItem];

            // Release it so the main menu owns it.
            [newItem release];
        }
    }
}

@end

/*
 * Class:     sun_lwawt_macosx_CMenuBar
 * Method:    nativeCreateMenuBar
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar
    (JNIEnv *env, jobject peer)
{
    CMenuBar *aCMenuBar = nil;
    JNF_COCOA_ENTER(env);

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

    // 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:[CMenuBar alloc] withObject:args waitUntilDone:YES];

    aCMenuBar = (CMenuBar *)[args objectAtIndex: 0];

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

    // [args release];

    // A strange memory managment after that.


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

/*
 * Class:     sun_lwawt_macosx_CMenuBar
 * Method:    nativeAddAtIndex
 * Signature: (JJI)V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CMenuBar_nativeAddAtIndex
    (JNIEnv *env, jobject peer,
     jlong menuBarObject, jlong menuObject, jint index)
{
    JNF_COCOA_ENTER(env);
    // Remove the specified item.
    [((CMenuBar *) jlong_to_ptr(menuBarObject)) javaAddMenu:(CMenu *) jlong_to_ptr(menuObject) atIndex:index];
    JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_CMenuBar
 * Method:    nativeDelMenu
 * Signature: (JI)V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CMenuBar_nativeDelMenu
    (JNIEnv *env, jobject peer, jlong menuBarObject, jint index)
{
    JNF_COCOA_ENTER(env);
    // Remove the specified item.
    [((CMenuBar *) jlong_to_ptr(menuBarObject)) javaDeleteMenu: index];
    JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_CMenuBar
 * Method:    nativeSetHelpMenu
 * Signature: (JJ)V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CMenuBar_nativeSetHelpMenu
    (JNIEnv *env, jobject peer, jlong menuBarObject, jlong menuObject)
{
    JNF_COCOA_ENTER(env);
    // Remove the specified item.
    [((CMenuBar *) jlong_to_ptr(menuBarObject)) javaSetHelpMenu: ((CMenu *)jlong_to_ptr(menuObject))];
    JNF_COCOA_EXIT(env);
}
