//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// OSXWindow.mm: Implementation of OSWindow for OSX

#include "osx/OSXWindow.h"

#include <set>
// Include Carbon to use the keycode names in Carbon's Event.h
#include <Carbon/Carbon.h>

#include "common/debug.h"

// On OSX 10.12 a number of AppKit interfaces have been renamed for consistency, and the previous
// symbols tagged as deprecated. However we can't simply use the new symbols as it would break
// compilation on our automated testing that doesn't use OSX 10.12 yet. So we just ignore the
// warnings.
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

// Some events such as "ShouldTerminate" are sent to the whole application so we keep a list of
// all the windows in order to forward the event to each of them. However this and calling pushEvent
// in ApplicationDelegate is inherently unsafe in a multithreaded environment.
static std::set<OSXWindow*> gAllWindows;

@interface Application : NSApplication
@end

@implementation Application
    - (void) sendEvent: (NSEvent*) nsEvent
    {
        if ([nsEvent type] == NSApplicationDefined)
        {
            for (auto window : gAllWindows)
            {
                if ([window->getNSWindow() windowNumber] == [nsEvent windowNumber])
                {
                    Event event;
                    event.Type = Event::EVENT_TEST;
                    window->pushEvent(event);
                }
            }
        }
        [super sendEvent: nsEvent];
    }
@end

// The Delegate receiving application-wide events.
@interface ApplicationDelegate : NSObject
@end

@implementation ApplicationDelegate
    - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication*) sender
    {
        Event event;
        event.Type = Event::EVENT_CLOSED;
        for (auto window : gAllWindows)
        {
            window->pushEvent(event);
        }
        return NSTerminateCancel;
    }
@end
static ApplicationDelegate *gApplicationDelegate = nil;

static bool InitializeAppKit()
{
    if (NSApp != nil)
    {
        return true;
    }

    // Initialize the global variable "NSApp"
    [Application sharedApplication];

    // Make us appear in the dock
    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];

    // Register our global event handler
    gApplicationDelegate = [[ApplicationDelegate alloc] init];
    if (gApplicationDelegate == nil)
    {
        return false;
    }
    [NSApp setDelegate: static_cast<id>(gApplicationDelegate)];

    // Set our status to "started" so we are not bouncing in the doc and can activate
    [NSApp finishLaunching];
    return true;
}

// NS's and CG's coordinate systems start at the bottom left, while OSWindow's coordinate
// system starts at the top left. This function converts the Y coordinate accordingly.
static float YCoordToFromCG(float y)
{
    float screenHeight = CGDisplayBounds(CGMainDisplayID()).size.height;
    return screenHeight - y;
}

// Delegate for window-wide events, note that the protocol doesn't contain anything input related.
@implementation WindowDelegate
    - (id) initWithWindow: (OSXWindow*) window
    {
        self = [super init];
        if (self != nil)
        {
            mWindow = window;
        }
        return self;
    }

    - (void) onOSXWindowDeleted
    {
        mWindow = nil;
    }

    - (BOOL) windowShouldClose: (id) sender
    {
        Event event;
        event.Type = Event::EVENT_CLOSED;
        mWindow->pushEvent(event);
        return NO;
    }

    - (void) windowDidResize: (NSNotification*) notification
    {
        NSSize windowSize = [[mWindow->getNSWindow() contentView] frame].size;
        Event event;
        event.Type = Event::EVENT_RESIZED;
        event.Size.Width = windowSize.width;
        event.Size.Height = windowSize.height;
        mWindow->pushEvent(event);
    }

    - (void) windowDidMove: (NSNotification*) notification
    {
        NSRect screenspace = [mWindow->getNSWindow() frame];
        Event event;
        event.Type = Event::EVENT_MOVED;
        event.Move.X = screenspace.origin.x;
        event.Move.Y = YCoordToFromCG(screenspace.origin.y + screenspace.size.height);
        mWindow->pushEvent(event);
    }

    - (void) windowDidBecomeKey: (NSNotification*) notification
    {
        Event event;
        event.Type = Event::EVENT_GAINED_FOCUS;
        mWindow->pushEvent(event);
        [self retain];
    }

    - (void) windowDidResignKey: (NSNotification*) notification
    {
        if (mWindow != nil)
        {
            Event event;
            event.Type = Event::EVENT_LOST_FOCUS;
            mWindow->pushEvent(event);
        }
        [self release];
    }
@end

static Key NSCodeToKey(int keyCode)
{
    // Missing KEY_PAUSE
    switch (keyCode)
    {
      case kVK_Shift:               return KEY_LSHIFT;
      case kVK_RightShift:          return KEY_RSHIFT;
      case kVK_Option:              return KEY_LALT;
      case kVK_RightOption:         return KEY_RALT;
      case kVK_Control:             return KEY_LCONTROL;
      case kVK_RightControl:        return KEY_RCONTROL;
      case kVK_Command:             return KEY_LSYSTEM;
      // Right System doesn't have a name, but shows up as 0x36.
      case 0x36:                    return KEY_RSYSTEM;
      case kVK_Function:            return KEY_MENU;

      case kVK_ANSI_Semicolon:      return KEY_SEMICOLON;
      case kVK_ANSI_Slash:          return KEY_SLASH;
      case kVK_ANSI_Equal:          return KEY_EQUAL;
      case kVK_ANSI_Minus:          return KEY_DASH;
      case kVK_ANSI_LeftBracket:    return KEY_LBRACKET;
      case kVK_ANSI_RightBracket:   return KEY_RBRACKET;
      case kVK_ANSI_Comma:          return KEY_COMMA;
      case kVK_ANSI_Period:         return KEY_PERIOD;
      case kVK_ANSI_Backslash:      return KEY_BACKSLASH;
      case kVK_ANSI_Grave:          return KEY_TILDE;
      case kVK_Escape:              return KEY_ESCAPE;
      case kVK_Space:               return KEY_SPACE;
      case kVK_Return:              return KEY_RETURN;
      case kVK_Delete:              return KEY_BACK;
      case kVK_Tab:                 return KEY_TAB;
      case kVK_PageUp:              return KEY_PAGEUP;
      case kVK_PageDown:            return KEY_PAGEDOWN;
      case kVK_End:                 return KEY_END;
      case kVK_Home:                return KEY_HOME;
      case kVK_Help:                return KEY_INSERT;
      case kVK_ForwardDelete:       return KEY_DELETE;
      case kVK_ANSI_KeypadPlus:     return KEY_ADD;
      case kVK_ANSI_KeypadMinus:    return KEY_SUBTRACT;
      case kVK_ANSI_KeypadMultiply: return KEY_MULTIPLY;
      case kVK_ANSI_KeypadDivide:   return KEY_DIVIDE;

      case kVK_F1:                  return KEY_F1;
      case kVK_F2:                  return KEY_F2;
      case kVK_F3:                  return KEY_F3;
      case kVK_F4:                  return KEY_F4;
      case kVK_F5:                  return KEY_F5;
      case kVK_F6:                  return KEY_F6;
      case kVK_F7:                  return KEY_F7;
      case kVK_F8:                  return KEY_F8;
      case kVK_F9:                  return KEY_F9;
      case kVK_F10:                 return KEY_F10;
      case kVK_F11:                 return KEY_F11;
      case kVK_F12:                 return KEY_F12;
      case kVK_F13:                 return KEY_F13;
      case kVK_F14:                 return KEY_F14;
      case kVK_F15:                 return KEY_F15;

      case kVK_LeftArrow:           return KEY_LEFT;
      case kVK_RightArrow:          return KEY_RIGHT;
      case kVK_DownArrow:           return KEY_DOWN;
      case kVK_UpArrow:             return KEY_UP;

      case kVK_ANSI_Keypad0:        return KEY_NUMPAD0;
      case kVK_ANSI_Keypad1:        return KEY_NUMPAD1;
      case kVK_ANSI_Keypad2:        return KEY_NUMPAD2;
      case kVK_ANSI_Keypad3:        return KEY_NUMPAD3;
      case kVK_ANSI_Keypad4:        return KEY_NUMPAD4;
      case kVK_ANSI_Keypad5:        return KEY_NUMPAD5;
      case kVK_ANSI_Keypad6:        return KEY_NUMPAD6;
      case kVK_ANSI_Keypad7:        return KEY_NUMPAD7;
      case kVK_ANSI_Keypad8:        return KEY_NUMPAD8;
      case kVK_ANSI_Keypad9:        return KEY_NUMPAD9;

      case kVK_ANSI_A:              return KEY_A;
      case kVK_ANSI_B:              return KEY_B;
      case kVK_ANSI_C:              return KEY_C;
      case kVK_ANSI_D:              return KEY_D;
      case kVK_ANSI_E:              return KEY_E;
      case kVK_ANSI_F:              return KEY_F;
      case kVK_ANSI_G:              return KEY_G;
      case kVK_ANSI_H:              return KEY_H;
      case kVK_ANSI_I:              return KEY_I;
      case kVK_ANSI_J:              return KEY_J;
      case kVK_ANSI_K:              return KEY_K;
      case kVK_ANSI_L:              return KEY_L;
      case kVK_ANSI_M:              return KEY_M;
      case kVK_ANSI_N:              return KEY_N;
      case kVK_ANSI_O:              return KEY_O;
      case kVK_ANSI_P:              return KEY_P;
      case kVK_ANSI_Q:              return KEY_Q;
      case kVK_ANSI_R:              return KEY_R;
      case kVK_ANSI_S:              return KEY_S;
      case kVK_ANSI_T:              return KEY_T;
      case kVK_ANSI_U:              return KEY_U;
      case kVK_ANSI_V:              return KEY_V;
      case kVK_ANSI_W:              return KEY_W;
      case kVK_ANSI_X:              return KEY_X;
      case kVK_ANSI_Y:              return KEY_Y;
      case kVK_ANSI_Z:              return KEY_Z;

      case kVK_ANSI_1:              return KEY_NUM1;
      case kVK_ANSI_2:              return KEY_NUM2;
      case kVK_ANSI_3:              return KEY_NUM3;
      case kVK_ANSI_4:              return KEY_NUM4;
      case kVK_ANSI_5:              return KEY_NUM5;
      case kVK_ANSI_6:              return KEY_NUM6;
      case kVK_ANSI_7:              return KEY_NUM7;
      case kVK_ANSI_8:              return KEY_NUM8;
      case kVK_ANSI_9:              return KEY_NUM9;
      case kVK_ANSI_0:              return KEY_NUM0;
    }

    return Key(0);
}

static void AddNSKeyStateToEvent(Event *event, int state)
{
    event->Key.Shift = state & NSShiftKeyMask;
    event->Key.Control = state & NSControlKeyMask;
    event->Key.Alt = state & NSAlternateKeyMask;
    event->Key.System = state & NSCommandKeyMask;
}

static MouseButton TranslateMouseButton(int button)
{
    switch (button)
    {
      case 2:
        return MOUSEBUTTON_MIDDLE;
      case 3:
        return MOUSEBUTTON_BUTTON4;
      case 4:
        return MOUSEBUTTON_BUTTON5;
      default:
        return MOUSEBUTTON_UNKNOWN;
    }
}

// Delegate for NSView events, mostly the input events
@implementation ContentView
    - (id) initWithWindow: (OSXWindow*) window
    {
        self = [super init];
        if (self != nil)
        {
            mWindow = window;
            mTrackingArea = nil;
            mCurrentModifier = 0;
            [self updateTrackingAreas];
        }
        return self;
    }

    - (void) dealloc
    {
        [mTrackingArea release];
        [super dealloc];
    }

    - (void) updateTrackingAreas
    {
        if (mTrackingArea != nil)
        {
            [self removeTrackingArea: mTrackingArea];
            [mTrackingArea release];
            mTrackingArea = nil;
        }

        NSRect bounds = [self bounds];
        NSTrackingAreaOptions flags = NSTrackingMouseEnteredAndExited |
                                      NSTrackingActiveInKeyWindow |
                                      NSTrackingCursorUpdate |
                                      NSTrackingInVisibleRect |
                                      NSTrackingAssumeInside;
        mTrackingArea = [[NSTrackingArea alloc] initWithRect: bounds
                                                    options: flags
                                                      owner: self
                                                   userInfo: nil];

        [self addTrackingArea: mTrackingArea];
        [super updateTrackingAreas];
    }

    // Helps with performance
    - (BOOL) isOpaque
    {
        return YES;
    }

    - (BOOL) canBecomeKeyView
    {
        return YES;
    }

    - (BOOL) acceptsFirstResponder
    {
        return YES;
    }

    // Handle mouse events from the NSResponder protocol
    - (float) translateMouseY: (float) y
    {
        return [self frame].size.height - y;
    }

    - (void) addButtonEvent: (NSEvent*) nsEvent type:(Event::EventType) eventType button:(MouseButton) button
    {
        Event event;
        event.Type = eventType;
        event.MouseButton.Button = button;
        event.MouseButton.X = [nsEvent locationInWindow].x;
        event.MouseButton.Y = [self translateMouseY: [nsEvent locationInWindow].y];
        mWindow->pushEvent(event);
    }

    - (void) mouseDown: (NSEvent*) event
    {
        [self addButtonEvent: event
                        type: Event::EVENT_MOUSE_BUTTON_PRESSED
                      button: MOUSEBUTTON_LEFT];
    }

    - (void) mouseDragged: (NSEvent*) event
    {
        [self mouseMoved: event];
    }

    - (void) mouseUp: (NSEvent*) event
    {
        [self addButtonEvent: event
                        type: Event::EVENT_MOUSE_BUTTON_RELEASED
                      button: MOUSEBUTTON_LEFT];
    }

    - (void) mouseMoved: (NSEvent*) nsEvent
    {
        Event event;
        event.Type = Event::EVENT_MOUSE_MOVED;
        event.MouseMove.X = [nsEvent locationInWindow].x;
        event.MouseMove.Y = [self translateMouseY: [nsEvent locationInWindow].y];
        mWindow->pushEvent(event);
    }

    - (void) mouseEntered: (NSEvent*) nsEvent
    {
        Event event;
        event.Type = Event::EVENT_MOUSE_ENTERED;
        mWindow->pushEvent(event);
    }

    - (void) mouseExited: (NSEvent*) nsEvent
    {
        Event event;
        event.Type = Event::EVENT_MOUSE_LEFT;
        mWindow->pushEvent(event);
    }

    - (void)rightMouseDown:(NSEvent *)event
    {
        [self addButtonEvent: event
                        type: Event::EVENT_MOUSE_BUTTON_PRESSED
                      button: MOUSEBUTTON_RIGHT];
    }

    - (void) rightMouseDragged: (NSEvent*) event
    {
        [self mouseMoved: event];
    }

    - (void) rightMouseUp: (NSEvent*)event
    {
        [self addButtonEvent: event
                        type: Event::EVENT_MOUSE_BUTTON_RELEASED
                      button: MOUSEBUTTON_RIGHT];
    }

    - (void) otherMouseDown: (NSEvent*) event
    {
        [self addButtonEvent: event
                        type: Event::EVENT_MOUSE_BUTTON_PRESSED
                      button: TranslateMouseButton([event buttonNumber])];
    }

    - (void) otherMouseDragged: (NSEvent*) event
    {
        [self mouseMoved: event];
    }

    - (void) otherMouseUp: (NSEvent*) event
    {
        [self addButtonEvent: event
                        type: Event::EVENT_MOUSE_BUTTON_RELEASED
                      button: TranslateMouseButton([event buttonNumber])];
    }

    - (void) scrollWheel: (NSEvent*) nsEvent
    {
        if (static_cast<int>([nsEvent deltaY]) == 0)
        {
            return;
        }

        Event event;
        event.Type = Event::EVENT_MOUSE_WHEEL_MOVED;
        event.MouseWheel.Delta = [nsEvent deltaY];
        mWindow->pushEvent(event);
    }

    // Handle key events from the NSResponder protocol
    - (void) keyDown: (NSEvent*) nsEvent
    {
        // TODO(cwallez) also send text events
        Event event;
        event.Type = Event::EVENT_KEY_PRESSED;
        event.Key.Code = NSCodeToKey([nsEvent keyCode]);
        AddNSKeyStateToEvent(&event, [nsEvent modifierFlags]);
        mWindow->pushEvent(event);
    }

    - (void) keyUp: (NSEvent*) nsEvent
    {
        Event event;
        event.Type = Event::EVENT_KEY_RELEASED;
        event.Key.Code = NSCodeToKey([nsEvent keyCode]);
        AddNSKeyStateToEvent(&event, [nsEvent modifierFlags]);
        mWindow->pushEvent(event);
    }

    // Modifier keys do not trigger keyUp/Down events but only flagsChanged events.
    - (void) flagsChanged: (NSEvent*) nsEvent
    {
        Event event;

        // Guess if the key has been pressed or released with the change of modifiers
        // It currently doesn't work when modifiers are unchanged, such as when pressing
        // both shift keys. GLFW has a solution for this but it requires tracking the
        // state of the keys. Implementing this is still TODO(cwallez)
        int modifier = [nsEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
        if (modifier < mCurrentModifier)
        {
            event.Type = Event::EVENT_KEY_RELEASED;
        }
        else
        {
            event.Type = Event::EVENT_KEY_PRESSED;
        }
        mCurrentModifier = modifier;

        event.Key.Code = NSCodeToKey([nsEvent keyCode]);
        AddNSKeyStateToEvent(&event, [nsEvent modifierFlags]);
        mWindow->pushEvent(event);
    }
@end

OSXWindow::OSXWindow()
    : mWindow(nil),
      mDelegate(nil),
      mView(nil)
{
}

OSXWindow::~OSXWindow()
{
    destroy();
}

bool OSXWindow::initialize(const std::string &name, size_t width, size_t height)
{
    if (!InitializeAppKit())
    {
        return false;
    }

    unsigned int styleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask |
                             NSMiniaturizableWindowMask;
    mWindow = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, width, height)
                                          styleMask: styleMask
                                            backing: NSBackingStoreBuffered
                                              defer: NO];

    if (mWindow == nil)
    {
        return false;
    }

    mDelegate = [[WindowDelegate alloc] initWithWindow: this];
    if (mDelegate == nil)
    {
        return false;
    }
    [mWindow setDelegate: static_cast<id>(mDelegate)];

    mView = [[ContentView alloc] initWithWindow: this];
    if (mView == nil)
    {
        return false;
    }
    [mView setWantsLayer:YES];

    [mWindow setContentView: mView];
    [mWindow setTitle: [NSString stringWithUTF8String: name.c_str()]];
    [mWindow setAcceptsMouseMovedEvents: YES];
    [mWindow center];

    [NSApp activateIgnoringOtherApps: YES];

    mX = 0;
    mY = 0;
    mWidth = width;
    mHeight = height;

    gAllWindows.insert(this);
    return true;
}

void OSXWindow::destroy()
{
    gAllWindows.erase(this);

    [mView release];
    mView = nil;
    [mDelegate onOSXWindowDeleted];
    [mDelegate release];
    mDelegate = nil;
    [mWindow release];
    mWindow = nil;
}

EGLNativeWindowType OSXWindow::getNativeWindow() const
{
    return [mView layer];
}

EGLNativeDisplayType OSXWindow::getNativeDisplay() const
{
    // TODO(cwallez): implement it once we have defined what EGLNativeDisplayType is
    return static_cast<EGLNativeDisplayType>(0);
}

void OSXWindow::messageLoop()
{
    @autoreleasepool
    {
        while (true)
        {
            NSEvent* event = [NSApp nextEventMatchingMask: NSAnyEventMask
                                                untilDate: [NSDate distantPast]
                                                   inMode: NSDefaultRunLoopMode
                                                  dequeue: YES];
            if (event == nil)
            {
                break;
            }

            if ([event type] == NSAppKitDefined)
            {
                continue;
            }
            [NSApp sendEvent: event];
        }
    }
}

void OSXWindow::setMousePosition(int x, int y)
{
    y = [mWindow frame].size.height - y -1;
    NSPoint screenspace;

    #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
        screenspace = [mWindow convertBaseToScreen: NSMakePoint(x, y)];
    #else
        screenspace = [mWindow convertRectToScreen: NSMakeRect(x, y, 0, 0)].origin;
    #endif
    CGWarpMouseCursorPosition(CGPointMake(screenspace.x, YCoordToFromCG(screenspace.y)));
}

bool OSXWindow::setPosition(int x, int y)
{
    // Given CG and NS's coordinate system, the "Y" position of a window is the Y coordinate
    // of the bottom of the window.
    int newBottom = [mWindow frame].size.height + y;
    NSRect emptyRect = NSMakeRect(x, YCoordToFromCG(newBottom), 0, 0);
    [mWindow setFrameOrigin: [mWindow frameRectForContentRect: emptyRect].origin];
    return true;
}

bool OSXWindow::resize(int width, int height)
{
    [mWindow setContentSize: NSMakeSize(width, height)];
    return true;
}

void OSXWindow::setVisible(bool isVisible)
{
    if (isVisible)
    {
        [mWindow makeKeyAndOrderFront: nil];
    }
    else
    {
        [mWindow orderOut: nil];
    }
}

void OSXWindow::signalTestEvent()
{
    @autoreleasepool
    {
        NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined
                                            location: NSMakePoint(0, 0)
                                       modifierFlags: 0
                                           timestamp: 0.0
                                        windowNumber: [mWindow windowNumber]
                                             context: nil
                                             subtype: 0
                                               data1: 0
                                               data2: 0];
        [NSApp postEvent: event atStart: YES];
    }
}

NSWindow* OSXWindow::getNSWindow() const
{
    return mWindow;
}

OSWindow *CreateOSWindow()
{
    return new OSXWindow;
}
