/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */

#import "common.h"
#import "com_sun_glass_events_ViewEvent.h"
#import "com_sun_glass_events_WindowEvent.h"
#import "com_sun_glass_ui_Window.h"
#import "com_sun_glass_ui_Window_Level.h"
#import "com_sun_glass_ui_mac_MacWindow.h"

#import "GlassMacros.h"
#import "GlassWindow.h"
#import "GlassWindow+Java.h"
#import "GlassWindow+Overrides.h"

@implementation GlassWindow (Overrides)

- (void)dealloc
{
    GET_MAIN_JENV;
    if (env != NULL)
    {
	    (*env)->DeleteGlobalRef(env, self->jWindow);
    	GLASS_CHECK_EXCEPTION(env);
    }
    
    self->jWindow = NULL;
    
    [super dealloc];
}

- (void)close
{
    [self _ungrabFocus];
    [super close];
}

#pragma mark --- Delegate

- (void)windowDidBecomeKey:(NSNotification *)notification
{
    if (self->fullscreenWindow)
    {
        return;
    }
    
    GET_MAIN_JENV;
    if (!self->isEnabled)
    {
        (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocusDisabled);
        return;
    }
    
    (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocus, com_sun_glass_events_WindowEvent_FOCUS_GAINED);
    
    if (self->menubar != nil)
    {
        [NSApp setMainMenu:self->menubar->menu];
    }
    [[NSApp mainMenu] update];
}

- (void)windowDidResignKey:(NSNotification *)notification
{
    if (self->fullscreenWindow)
    {
        return;
    }
    
    [self _ungrabFocus];
    
    GET_MAIN_JENV;
    (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyFocus, com_sun_glass_events_WindowEvent_FOCUS_LOST);
}

- (void)windowWillClose:(NSNotification *)notification
{
    // Unparent self. Otherwise the code hangs
    if ([self parentWindow])
    {
        [[self parentWindow] removeChildWindow:self];
    }
    
    // Call the notification method
    GET_MAIN_JENV;
    (*env)->CallVoidMethod(env, self->jWindow, jWindowNotifyDestroy);
    
    // Finally, close owned windows to mimic MS Windows behavior
    NSArray *children = [self childWindows];
    for (int i=0; i<[children count]; i++)
    {
        NSWindow *child = (NSWindow*)[children objectAtIndex:i];
        [child close];
    }
}

- (void)windowWillMove:(NSNotification *)notification
{
    //NSLog(@"windowWillMove");
}

- (void)windowDidMove:(NSNotification *)notification
{
    //NSLog(@"windowDidMove");
    [self _sendJavaWindowMoveEventForFrame:[self _flipFrame]];
}

- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
{
    //NSLog(@"windowWillResize");
    return proposedFrameSize;
}

- (void)windowDidResize:(NSNotification *)notification
{
    //NSLog(@"windowDidResize");
    // suppress window resize event if we're in the middle of maximizing, otherwise the maximize state gets reset
    [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESIZE forFrame:[self _flipFrame]];
}

- (void)windowDidMiniaturize:(NSNotification *)notification
{
    [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_MINIMIZE forFrame:[self _flipFrame]];
}

- (void)windowDidDeminiaturize:(NSNotification *)notification
{
    [self _sendJavaWindowResizeEvent:com_sun_glass_events_WindowEvent_RESTORE forFrame:[self _flipFrame]];
}

- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
{
    [self _sendJavaWindowMoveEventForFrame:newFrame]; // need to send move event before maximize
    GET_MAIN_JENV;
    (*env)->CallVoidMethod(env, jWindow, jWindowNotifyResize, com_sun_glass_events_WindowEvent_MAXIMIZE, (int)newFrame.size.width, (int)newFrame.size.height);
    
    return YES;
}

- (void)windowWillEnterFullScreen:(NSNotification *)notification
{
    //NSLog(@"windowWillEnterFullScreen");
}

- (void)windowDidEnterFullScreen:(NSNotification *)notification
{
    //NSLog(@"windowDidEnterFullScreen");
    
    GET_MAIN_JENV;
    (*env)->CallVoidMethod(env, [[self->view delegate] jView], jHandleViewEvent, com_sun_glass_events_ViewEvent_FULLSCREEN_ENTER);
}

- (void)windowWillExitFullScreen:(NSNotification *)notification
{
    //NSLog(@"windowWillExitFullScreen");
}

- (void)windowDidExitFullScreen:(NSNotification *)notification 
{
    //NSLog(@"windowDidExitFullScreen");
    
    GET_MAIN_JENV;
    (*env)->CallVoidMethod(env, [[self->view delegate] jView], jHandleViewEvent, com_sun_glass_events_ViewEvent_FULLSCREEN_EXIT);
}

- (void)sendEvent:(NSEvent *)event
{
    if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown)
    {
        NSPoint p = [NSEvent mouseLocation];
        NSRect frame = [self frame];
        NSRect contentRect = [self contentRectForFrameRect:frame];
        
        if (p.y >= (frame.origin.y + contentRect.size.height))
        {
            // Click to the titlebar
            [self _ungrabFocus];
        }
        
        [self _checkUngrab];
    }
    [super sendEvent:event];
}

#pragma mark --- NSWindow

// Window vs Panel API
- (BOOL)canBecomeMainWindow
{
    if (!self->isEnabled)
    {
        // We'll send FOCUS_DISABLED
        return YES;
    }
    return self->isFocusable;
}

// Window vs Panel API
- (void)setHidesOnDeactivate:(BOOL)hideOnDeactivate
{
	[super setHidesOnDeactivate:NO];
}

// Window vs Panel API
- (BOOL)hidesOnDeactivate
{
    return NO;
}

// Window vs Panel API
- (void)setWorksWhenModal:(BOOL)worksWhenModal
{
	[super setWorksWhenModal:NO];
}

// Window vs Panel API
- (BOOL)worksWhenModal
{
    return NO;
}

- (BOOL)canBecomeKeyWindow
{
    if (!self->isEnabled)
    {
        // We'll send FOCUS_DISABLED
        return YES;
    }
    return self->isFocusable;
}

- (BOOL)windowShouldClose:(NSNotification *)notification
{
    if (self->isEnabled)
    {
        GET_MAIN_JENV;
        (*env)->CallVoidMethod(env, jWindow, jWindowNotifyClose);
    }
    
    // it's up to app to decide if the window should be closed
    return FALSE;
}

- (void)setBackgroundColor:(NSColor *)color
{
    if (self->isTransparent == NO)
    {
        // allow color if we're opaque
        [super setBackgroundColor:color];
    }
    else
    {
        // for transparent window, ignore and set to clear color
        // FIXME: do we want to store the background color in case we switch to non-transparent mode?
        [super setBackgroundColor:[NSColor clearColor]];
    }
}

#pragma mark --- Title Icon

- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
{
    return NO;
}

- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard
{
    return NO;
}

- (NSButton *)standardWindowButton:(NSWindowButton)type
{
    NSButton *button = [super standardWindowButton:type];
    switch (type)
    {
        case NSWindowDocumentIconButton:
            // prevent the button from being clicked on
            [button setAcceptsTouchEvents:NO];
            [button setAction:nil];
            [button setEnabled:NO];
            break;
    }
    return button;
}

@end
