/*
 * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"
#import "PlatformEventFactoryMac.h"

#if PLATFORM(MAC)

#import "KeyEventCocoa.h"
#import "Logging.h"
#import "PlatformScreen.h"
#import "Scrollbar.h"
#import "WindowsKeyboardCodes.h"
#import <Carbon/Carbon.h>
#import <mach/mach_time.h>
#import <pal/spi/mac/HIToolboxSPI.h>
#import <pal/spi/mac/NSEventSPI.h>
#import <pal/spi/mac/NSMenuSPI.h>
#import <wtf/ASCIICType.h>
#import <wtf/WallTime.h>

namespace WebCore {

NSPoint globalPoint(const NSPoint& windowPoint, NSWindow *window)
{
    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    return flipScreenPoint([window convertBaseToScreen:windowPoint], screen(window));
    ALLOW_DEPRECATED_DECLARATIONS_END
}

static NSPoint globalPointForEvent(NSEvent *event)
{
    switch ([event type]) {
    case NSEventTypePressure:
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeMouseEntered:
    case NSEventTypeMouseExited:
    case NSEventTypeMouseMoved:
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseDragged:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseDragged:
    case NSEventTypeRightMouseUp:
    case NSEventTypeScrollWheel:
        return globalPoint([event locationInWindow], [event window]);
    default:
        return { 0, 0 };
    }
}

static IntPoint pointForEvent(NSEvent *event, NSView *windowView)
{
    switch ([event type]) {
    case NSEventTypePressure:
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeMouseEntered:
    case NSEventTypeMouseExited:
    case NSEventTypeMouseMoved:
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseDragged:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseDragged:
    case NSEventTypeRightMouseUp:
    case NSEventTypeScrollWheel: {
        // Note: This will have its origin at the bottom left of the window unless windowView is flipped.
        // In those cases, the Y coordinate gets flipped by Widget::convertFromContainingWindow.
        NSPoint location = [event locationInWindow];
        if (windowView)
            location = [windowView convertPoint:location fromView:nil];
        return IntPoint(location);
    }
    default:
        return IntPoint();
    }
}

static MouseButton mouseButtonForEvent(NSEvent *event)
{
    switch ([event type]) {
    case NSEventTypePressure:
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeLeftMouseDragged:
        return LeftButton;
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseUp:
    case NSEventTypeRightMouseDragged:
        return RightButton;
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeOtherMouseDragged:
        return MiddleButton;
    default:
        return NoButton;
    }
}

static unsigned short currentlyPressedMouseButtons()
{
    return static_cast<unsigned short>([NSEvent pressedMouseButtons]);
}

static PlatformEvent::Type mouseEventTypeForEvent(NSEvent* event)
{
    switch ([event type]) {
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeMouseEntered:
    case NSEventTypeMouseExited:
    case NSEventTypeMouseMoved:
    case NSEventTypeOtherMouseDragged:
    case NSEventTypeRightMouseDragged:
        return PlatformEvent::MouseMoved;
    case NSEventTypeLeftMouseDown:
    case NSEventTypeRightMouseDown:
    case NSEventTypeOtherMouseDown:
        return PlatformEvent::MousePressed;
    case NSEventTypeLeftMouseUp:
    case NSEventTypeRightMouseUp:
    case NSEventTypeOtherMouseUp:
        return PlatformEvent::MouseReleased;
    default:
        return PlatformEvent::MouseMoved;
    }
}

static int clickCountForEvent(NSEvent *event)
{
    switch ([event type]) {
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseUp:
    case NSEventTypeRightMouseDragged:
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeOtherMouseDragged:
        return [event clickCount];
    default:
        return 0;
    }
}

static PlatformWheelEventPhase phaseFromNSEventPhase(NSEventPhase eventPhase)
{
    switch (eventPhase) {
    case NSEventPhaseNone:
        return PlatformWheelEventPhase::None;
    case NSEventPhaseBegan:
        return PlatformWheelEventPhase::Began;
    case NSEventPhaseStationary:
        return PlatformWheelEventPhase::Stationary;
    case NSEventPhaseChanged:
        return PlatformWheelEventPhase::Changed;
    case NSEventPhaseEnded:
        return PlatformWheelEventPhase::Ended;
    case NSEventPhaseCancelled:
        return PlatformWheelEventPhase::Cancelled;
    case NSEventPhaseMayBegin:
        return PlatformWheelEventPhase::MayBegin;
    }

    return PlatformWheelEventPhase::None;
}

static PlatformWheelEventPhase momentumPhaseForEvent(NSEvent *event)
{
    return phaseFromNSEventPhase([event momentumPhase]);
}

static PlatformWheelEventPhase phaseForEvent(NSEvent *event)
{
    return phaseFromNSEventPhase([event phase]);
}

static inline String textFromEvent(NSEvent* event)
{
    if ([event type] == NSEventTypeFlagsChanged)
        return emptyString();
    return String([event characters]);
}

static inline String unmodifiedTextFromEvent(NSEvent* event)
{
    if ([event type] == NSEventTypeFlagsChanged)
        return emptyString();
    return String([event charactersIgnoringModifiers]);
}

String keyForKeyEvent(NSEvent *event)
{
    switch ([event keyCode]) {
    case kVK_RightCommand:
    case kVK_Command:
        return "Meta"_s;
    case kVK_Shift:
    case kVK_RightShift:
        return "Shift"_s;
    case kVK_CapsLock:
        return "CapsLock"_s;
    case kVK_Option: // Left Alt.
    case kVK_RightOption: // Right Alt.
        return "Alt"_s;
    case kVK_Control:
    case kVK_RightControl:
        return "Control"_s;
    }

    // If the event is an NSEventTypeFlagsChanged events and we have not returned yet then this means we could not
    // identify the modifier key. We return now and report the key as "Unidentified".
    // Note that [event characters] below raises an exception if called on an NSEventTypeFlagsChanged event.
    if ([event type] == NSEventTypeFlagsChanged)
        return "Unidentified"_s;

    // If more than one key is being pressed and the key combination includes one or more modifier keys
    // that result in the key no longer producing a printable character (e.g., Control + a), then the
    // key value should be the printable key value that would have been produced if the key had been
    // typed with the default keyboard layout with no modifier keys except for Shift and AltGr applied.
    // See <https://www.w3.org/TR/2015/WD-uievents-20151215/#keys-guidelines>.
    bool isControlDown = ([event modifierFlags] & NSEventModifierFlagControl);
    NSString *s = isControlDown ? [event charactersIgnoringModifiers] : [event characters];
    auto length = [s length];
    // characters / charactersIgnoringModifiers return an empty string for dead keys.
    // https://developer.apple.com/reference/appkit/nsevent/1534183-characters
    if (!length)
        return "Dead"_s;
    // High unicode codepoints are coded with a character sequence in Mac OS X.
    if (length > 1)
        return s;
    return keyForCharCode([s characterAtIndex:0]);
}

// https://w3c.github.io/uievents-code/
String codeForKeyEvent(NSEvent *event)
{
    switch ([event keyCode]) {
    // Keys in the alphanumeric section.
    case kVK_ANSI_Grave: return "Backquote"_s;
    case kVK_ANSI_Backslash: return "Backslash"_s;
    case kVK_Delete: return "Backspace"_s;
    case kVK_ANSI_LeftBracket: return "BracketLeft"_s;
    case kVK_ANSI_RightBracket: return "BracketRight"_s;
    case kVK_ANSI_Comma: return "Comma"_s;
    case kVK_ANSI_0: return "Digit0"_s;
    case kVK_ANSI_1: return "Digit1"_s;
    case kVK_ANSI_2: return "Digit2"_s;
    case kVK_ANSI_3: return "Digit3"_s;
    case kVK_ANSI_4: return "Digit4"_s;
    case kVK_ANSI_5: return "Digit5"_s;
    case kVK_ANSI_6: return "Digit6"_s;
    case kVK_ANSI_7: return "Digit7"_s;
    case kVK_ANSI_8: return "Digit8"_s;
    case kVK_ANSI_9: return "Digit9"_s;
    case kVK_ANSI_Equal: return "Equal"_s;
    case kVK_ISO_Section: return "IntlBackslash"_s;
    case kVK_JIS_Underscore: return "IntlRo"_s;
    case kVK_JIS_Yen: return "IntlYen"_s;
    case kVK_ANSI_A: return "KeyA"_s;
    case kVK_ANSI_B: return "KeyB"_s;
    case kVK_ANSI_C: return "KeyC"_s;
    case kVK_ANSI_D: return "KeyD"_s;
    case kVK_ANSI_E: return "KeyE"_s;
    case kVK_ANSI_F: return "KeyF"_s;
    case kVK_ANSI_G: return "KeyG"_s;
    case kVK_ANSI_H: return "KeyH"_s;
    case kVK_ANSI_I: return "KeyI"_s;
    case kVK_ANSI_J: return "KeyJ"_s;
    case kVK_ANSI_K: return "KeyK"_s;
    case kVK_ANSI_L: return "KeyL"_s;
    case kVK_ANSI_M: return "KeyM"_s;
    case kVK_ANSI_N: return "KeyN"_s;
    case kVK_ANSI_O: return "KeyO"_s;
    case kVK_ANSI_P: return "KeyP"_s;
    case kVK_ANSI_Q: return "KeyQ"_s;
    case kVK_ANSI_R: return "KeyR"_s;
    case kVK_ANSI_S: return "KeyS"_s;
    case kVK_ANSI_T: return "KeyT"_s;
    case kVK_ANSI_U: return "KeyU"_s;
    case kVK_ANSI_V: return "KeyV"_s;
    case kVK_ANSI_W: return "KeyW"_s;
    case kVK_ANSI_X: return "KeyX"_s;
    case kVK_ANSI_Y: return "KeyY"_s;
    case kVK_ANSI_Z: return "KeyZ"_s;
    case kVK_ANSI_Minus: return "Minus"_s;
    case kVK_ANSI_Period: return "Period"_s;
    case kVK_ANSI_Quote: return "Quote"_s;
    case kVK_ANSI_Semicolon: return "Semicolon"_s;
    case kVK_ANSI_Slash: return "Slash"_s;

    // Functional keys in alphanumeric section.
    case kVK_Option: return "AltLeft"_s;
    case kVK_RightOption: return "AltRight"_s;
    case kVK_CapsLock: return "CapsLock"_s;
    // ContextMenu.
    case kVK_Control: return "ControlLeft"_s;
    case kVK_RightControl: return "ControlRight"_s;
    case kVK_Return: return "Enter"_s; //  Labeled Return on Apple keyboards.
    case kVK_Command: return "MetaLeft"_s;
    case kVK_RightCommand: return "MetaRight"_s;
    case kVK_Shift: return "ShiftLeft"_s;
    case kVK_RightShift: return "ShiftRight"_s;
    case kVK_Space: return "Space"_s;
    case kVK_Tab: return "Tab"_s;

    // Functional keys found on Japanese and Korean keyboards.
    // Convert.
    case kVK_JIS_Kana: return "KanaMode"_s;
    // Lang1.
    case kVK_JIS_Eisu: return "Lang2"_s; // Japanese (Mac keyboard): eisu.
    // Lang3.
    // Lang4.
    // Lang5.
    // NonConvert.

    // Keys in the ControlPad section.
    case kVK_ForwardDelete: return "Delete"_s;
    case kVK_End: return "End"_s;
    case kVK_Help: return "Help"_s;
    case kVK_Home: return "Home"_s;
    // Insert: Not present on Apple keyboards.
    case kVK_PageDown: return "PageDown"_s;
    case kVK_PageUp: return "PageUp"_s;

    // Keys in the ArrowPad section.
    case kVK_DownArrow: return "ArrowDown"_s;
    case kVK_LeftArrow: return "ArrowLeft"_s;
    case kVK_RightArrow: return "ArrowRight"_s;
    case kVK_UpArrow: return "ArrowUp"_s;

    // Keys in the Numpad section.
    case kVK_ANSI_KeypadClear: return "NumLock"_s; // The specification says to use "NumLock" on Mac for the numpad Clear key.
    case kVK_ANSI_Keypad0: return "Numpad0"_s;
    case kVK_ANSI_Keypad1: return "Numpad1"_s;
    case kVK_ANSI_Keypad2: return "Numpad2"_s;
    case kVK_ANSI_Keypad3: return "Numpad3"_s;
    case kVK_ANSI_Keypad4: return "Numpad4"_s;
    case kVK_ANSI_Keypad5: return "Numpad5"_s;
    case kVK_ANSI_Keypad6: return "Numpad6"_s;
    case kVK_ANSI_Keypad7: return "Numpad7"_s;
    case kVK_ANSI_Keypad8: return "Numpad8"_s;
    case kVK_ANSI_Keypad9: return "Numpad9"_s;
    case kVK_ANSI_KeypadPlus: return "NumpadAdd"_s;
    // NumpadBackspace.
    // NumpadClear: The specification says that the numpad Clear key should always be encoded as "NumLock" on Mac.
    // NumpadClearEntry.
    case kVK_JIS_KeypadComma: return "NumpadComma"_s;
    case kVK_ANSI_KeypadDecimal: return "NumpadDecimal"_s;
    case kVK_ANSI_KeypadDivide: return "NumpadDivide"_s;
    case kVK_ANSI_KeypadEnter: return "NumpadEnter"_s;
    case kVK_ANSI_KeypadEquals: return "NumpadEqual"_s;
    // NumpadHash.
    // NumpadMemoryAdd.
    // NumpadMemoryClear.
    // NumpadMemoryRecall.
    // NumpadMemoryStore.
    // NumpadMemorySubtract.
    case kVK_ANSI_KeypadMultiply: return "NumpadMultiply"_s;
    // NumpadParenLeft.
    // NumpadParenRight.
    // NumpadStar: The specification says to use "NumpadMultiply" for the * key on numeric keypads.
    case kVK_ANSI_KeypadMinus: return "NumpadSubtract"_s;

    // Keys in the Function section.
    case kVK_Escape: return "Escape"_s;
    case kVK_F1: return "F1"_s;
    case kVK_F2: return "F2"_s;
    case kVK_F3: return "F3"_s;
    case kVK_F4: return "F4"_s;
    case kVK_F5: return "F5"_s;
    case kVK_F6: return "F6"_s;
    case kVK_F7: return "F7"_s;
    case kVK_F8: return "F8"_s;
    case kVK_F9: return "F9"_s;
    case kVK_F10: return "F10"_s;
    case kVK_F11: return "F11"_s;
    case kVK_F12: return "F12"_s;
    case kVK_F13: return "F13"_s;
    case kVK_F14: return "F14"_s;
    case kVK_F15: return "F15"_s;
    case kVK_F16: return "F16"_s;
    case kVK_F17: return "F17"_s;
    case kVK_F18: return "F18"_s;
    case kVK_F19: return "F19"_s;
    case kVK_F20: return "F20"_s;
    // Fn: This is typically a hardware key that does not generate a separate code.
    // FnLock.
    // PrintScreen.
    // ScrollLock.
    // Pause.

    // Media keys.
    // BrowserBack.
    // BrowserFavorites.
    // BrowserForward.
    // BrowserHome.
    // BrowserRefresh.
    // BrowserSearch.
    // BrowserStop.
    // Eject.
    // LaunchApp1.
    // LaunchApp2.
    // LaunchMail.
    // MediaPlayPause.
    // MediaSelect.
    // MediaStop.
    // MediaTrackNext.
    // MediaTrackPrevious.
    // Power.
    // Sleep.
    case kVK_VolumeDown: return "AudioVolumeDown"_s;
    case kVK_Mute: return "AudioVolumeMute"_s;
    case kVK_VolumeUp: return "AudioVolumeUp"_s;
    // WakeUp.

    // Legacy modifier keys.
    // Hyper.
    // Super.
    // Turbo.

    // Legacy process control keys.
    // Abort.
    // Resume.
    // Suspend.

    // Legacy editing keys.
    // Again.
    // Copy.
    // Cut.
    // Find.
    // Open.
    // Paste.
    // Props.
    // Select.
    // Undo.

    // Keys found on international keyboards.
    // Hiragana.
    // Katakana.

    default:
        return "Unidentified"_s;
    }
}

String keyIdentifierForKeyEvent(NSEvent* event)
{
    if ([event type] == NSEventTypeFlagsChanged) {
        switch ([event keyCode]) {
        case 54: // Right Command
        case 55: // Left Command
            return "Meta"_str;

        case 57: // Capslock
            return "CapsLock"_str;

        case 56: // Left Shift
        case 60: // Right Shift
            return "Shift"_str;

        case 58: // Left Alt
        case 61: // Right Alt
            return "Alt"_str;

        case 59: // Left Ctrl
        case 62: // Right Ctrl
            return "Control"_str;

        default:
            ASSERT_NOT_REACHED();
            return emptyString();
        }
    }
    
    NSString *s = [event charactersIgnoringModifiers];
    if ([s length] != 1) {
        LOG(Events, "received an unexpected number of characters in key event: %u", [s length]);
        return "Unidentified";
    }
    return keyIdentifierForCharCode([s characterAtIndex:0]);
}

static bool isKeypadEvent(NSEvent* event)
{
    // Check that this is the type of event that has a keyCode.
    switch ([event type]) {
    case NSEventTypeKeyDown:
    case NSEventTypeKeyUp:
    case NSEventTypeFlagsChanged:
        break;
    default:
        return false;
    }

    if ([event modifierFlags] & NSEventModifierFlagNumericPad)
        return true;

    switch ([event keyCode]) {
    case 71: // Clear
    case 81: // =
    case 75: // /
    case 67: // *
    case 78: // -
    case 69: // +
    case 76: // Enter
    case 65: // .
    case 82: // 0
    case 83: // 1
    case 84: // 2
    case 85: // 3
    case 86: // 4
    case 87: // 5
    case 88: // 6
    case 89: // 7
    case 91: // 8
    case 92: // 9
        return true;
    }
     
     return false;
}

int windowsKeyCodeForKeyEvent(NSEvent* event)
{
    int code = 0;
    // There are several kinds of characters for which we produce key code from char code:
    // 1. Roman letters. Windows keyboard layouts affect both virtual key codes and character codes for these,
    //    so e.g. 'A' gets the same keyCode on QWERTY, AZERTY or Dvorak layouts.
    // 2. Keys for which there is no known Mac virtual key codes, like PrintScreen.
    // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout,
    //    but see comment in windowsKeyCodeForCharCode().
    if (!isKeypadEvent(event) && ([event type] == NSEventTypeKeyDown || [event type] == NSEventTypeKeyUp)) {
        // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first.
        NSString* s = [event characters];
        code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0;
        if (code)
            return code;

        // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on -[NSEvent keyCode] below.
        s = [event charactersIgnoringModifiers];
        code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0;
        if (code)
            return code;
    }

    // Map Mac virtual key code directly to Windows one for any keys not handled above.
    // E.g. the key next to Caps Lock has the same Event.keyCode on U.S. keyboard ('A') and on Russian keyboard (CYRILLIC LETTER EF).
    return windowsKeyCodeForKeyCode([event keyCode]);
}

static CFAbsoluteTime systemStartupTime;

static void updateSystemStartupTimeIntervalSince1970()
{
    // CFAbsoluteTimeGetCurrent() provides the absolute time in seconds since 2001.
    // mach_absolute_time() provides a relative system time since startup minus the time the computer was suspended.
    mach_timebase_info_data_t timebase_info;
    mach_timebase_info(&timebase_info);
    double elapsedTimeSinceStartup = static_cast<double>(mach_absolute_time()) * timebase_info.numer / timebase_info.denom / 1e9;
    systemStartupTime = kCFAbsoluteTimeIntervalSince1970 + CFAbsoluteTimeGetCurrent() - elapsedTimeSinceStartup;
}

static CFTimeInterval cachedStartupTimeIntervalSince1970()
{
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        void (^updateBlock)(NSNotification *) = Block_copy(^(NSNotification *){ updateSystemStartupTimeIntervalSince1970(); });
        [[[NSWorkspace sharedWorkspace] notificationCenter] addObserverForName:NSWorkspaceDidWakeNotification
                                                                        object:nil
                                                                         queue:nil
                                                                    usingBlock:updateBlock];
        [[NSNotificationCenter defaultCenter] addObserverForName:NSSystemClockDidChangeNotification
                                                          object:nil
                                                           queue:nil
                                                      usingBlock:updateBlock];
        Block_release(updateBlock);

        updateSystemStartupTimeIntervalSince1970();
    });
    return systemStartupTime;
}

WallTime eventTimeStampSince1970(NSTimeInterval timestamp)
{
    return WallTime::fromRawSeconds(static_cast<double>(cachedStartupTimeIntervalSince1970() + timestamp));
}

static inline bool isKeyUpEvent(NSEvent *event)
{
    if ([event type] != NSEventTypeFlagsChanged)
        return [event type] == NSEventTypeKeyUp;
    // FIXME: This logic fails if the user presses both Shift keys at once, for example:
    // we treat releasing one of them as keyDown.
    switch ([event keyCode]) {
    case 54: // Right Command
    case 55: // Left Command
        return !([event modifierFlags] & NSEventModifierFlagCommand);

    case 57: // Capslock
        return !([event modifierFlags] & NSEventModifierFlagCapsLock);

    case 56: // Left Shift
    case 60: // Right Shift
        return !([event modifierFlags] & NSEventModifierFlagShift);

    case 58: // Left Alt
    case 61: // Right Alt
        return !([event modifierFlags] & NSEventModifierFlagOption);

    case 59: // Left Ctrl
    case 62: // Right Ctrl
        return !([event modifierFlags] & NSEventModifierFlagControl);

    case 63: // Function
        return !([event modifierFlags] & NSEventModifierFlagFunction);
    }
    return false;
}

OptionSet<PlatformEvent::Modifier> modifiersForEvent(NSEvent *event)
{
    OptionSet<PlatformEvent::Modifier> modifiers;

    if (event.modifierFlags & NSEventModifierFlagShift)
        modifiers.add(PlatformEvent::Modifier::ShiftKey);
    if (event.modifierFlags & NSEventModifierFlagControl)
        modifiers.add(PlatformEvent::Modifier::ControlKey);
    if (event.modifierFlags & NSEventModifierFlagOption)
        modifiers.add(PlatformEvent::Modifier::AltKey);
    if (event.modifierFlags & NSEventModifierFlagCommand)
        modifiers.add(PlatformEvent::Modifier::MetaKey);
    if (event.modifierFlags & NSEventModifierFlagCapsLock)
        modifiers.add(PlatformEvent::Modifier::CapsLockKey);

    return modifiers;
}

static int typeForEvent(NSEvent *event)
{
    return static_cast<int>([NSMenu menuTypeForEvent:event]);
}

void getWheelEventDeltas(NSEvent *event, float& deltaX, float& deltaY, BOOL& continuous)
{
    ASSERT(event);
    if (event.hasPreciseScrollingDeltas) {
        deltaX = event.scrollingDeltaX;
        deltaY = event.scrollingDeltaY;
        continuous = YES;
    } else {
        deltaX = event.deltaX;
        deltaY = event.deltaY;
        continuous = NO;
    }
}

UInt8 keyCharForEvent(NSEvent *event)
{
    EventRef eventRef = (EventRef)[event _eventRef];
    if (!eventRef)
        return 0;

    ByteCount keyCharCount = 0;
    if (GetEventParameter(eventRef, kEventParamKeyMacCharCodes, typeChar, 0, 0, &keyCharCount, 0) != noErr)
        return 0;
    if (keyCharCount != 1)
        return 0;

    UInt8 keyChar = 0;
    if (GetEventParameter(eventRef, kEventParamKeyMacCharCodes, typeChar, 0, sizeof(keyChar), &keyCharCount, &keyChar) != noErr)
        return 0;
    
    return keyChar;
}

class PlatformMouseEventBuilder : public PlatformMouseEvent {
public:
    PlatformMouseEventBuilder(NSEvent *event, NSEvent *correspondingPressureEvent, NSView *windowView)
    {
        // PlatformEvent
        m_type = mouseEventTypeForEvent(event);

        BOOL eventIsPressureEvent = [event type] == NSEventTypePressure;
        if (eventIsPressureEvent) {
            // Since AppKit doesn't send mouse events for force down or force up, we have to use the current pressure
            // event and correspondingPressureEvent to detect if this is MouseForceDown, MouseForceUp, or just MouseForceChanged.
            if (correspondingPressureEvent.stage == 1 && event.stage == 2)
                m_type = PlatformEvent::MouseForceDown;
            else if (correspondingPressureEvent.stage == 2 && event.stage == 1)
                m_type = PlatformEvent::MouseForceUp;
            else
                m_type = PlatformEvent::MouseForceChanged;
        }

        m_modifiers = modifiersForEvent(event);
        m_timestamp = eventTimeStampSince1970(event.timestamp);

        // PlatformMouseEvent
        m_position = pointForEvent(event, windowView);
        m_globalPosition = IntPoint(globalPointForEvent(event));
        m_button = mouseButtonForEvent(event);
        m_buttons = currentlyPressedMouseButtons();
        m_clickCount = clickCountForEvent(event);
        m_movementDelta = IntPoint(event.deltaX, event.deltaY);

        m_force = 0;
        int stage = eventIsPressureEvent ? event.stage : correspondingPressureEvent.stage;
        double pressure = eventIsPressureEvent ? event.pressure : correspondingPressureEvent.pressure;
        m_force = pressure + stage;

        // Mac specific
        m_modifierFlags = [event modifierFlags];
        m_eventNumber = [event eventNumber];
        m_menuTypeForEvent = typeForEvent(event);
    }
};

PlatformMouseEvent PlatformEventFactory::createPlatformMouseEvent(NSEvent *event, NSEvent *correspondingPressureEvent, NSView *windowView)
{
    return PlatformMouseEventBuilder(event, correspondingPressureEvent, windowView);
}


class PlatformWheelEventBuilder : public PlatformWheelEvent {
public:
    PlatformWheelEventBuilder(NSEvent *event, NSView *windowView)
    {
        // PlatformEvent
        m_type = PlatformEvent::Wheel;
        m_modifiers = modifiersForEvent(event);
        m_timestamp = eventTimeStampSince1970(event.timestamp);

        // PlatformWheelEvent
        m_position = pointForEvent(event, windowView);
        m_globalPosition = IntPoint(globalPointForEvent(event));
        m_granularity = ScrollByPixelWheelEvent;

        BOOL continuous;
        getWheelEventDeltas(event, m_deltaX, m_deltaY, continuous);
        if (continuous) {
            m_wheelTicksX = m_deltaX / static_cast<float>(Scrollbar::pixelsPerLineStep());
            m_wheelTicksY = m_deltaY / static_cast<float>(Scrollbar::pixelsPerLineStep());
        } else {
            m_wheelTicksX = m_deltaX;
            m_wheelTicksY = m_deltaY;
            m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep());
            m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep());
        }

        m_phase = phaseForEvent(event);
        m_momentumPhase = momentumPhaseForEvent(event);
        m_hasPreciseScrollingDeltas = continuous;
        m_directionInvertedFromDevice = [event isDirectionInvertedFromDevice];
    }
};

PlatformWheelEvent PlatformEventFactory::createPlatformWheelEvent(NSEvent *event, NSView *windowView)
{
    return PlatformWheelEventBuilder(event, windowView);
}


class PlatformKeyboardEventBuilder : public PlatformKeyboardEvent {
public:
    PlatformKeyboardEventBuilder(NSEvent *event)
    {
        // PlatformEvent
        m_type = isKeyUpEvent(event) ? PlatformEvent::KeyUp : PlatformEvent::KeyDown;
        m_modifiers = modifiersForEvent(event);
        m_timestamp = eventTimeStampSince1970(event.timestamp);

        // PlatformKeyboardEvent
        m_text = textFromEvent(event);
        m_unmodifiedText = unmodifiedTextFromEvent(event);
        m_keyIdentifier = keyIdentifierForKeyEvent(event);
        m_key = keyForKeyEvent(event);
        m_code = codeForKeyEvent(event);
        m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event);
        m_autoRepeat = [event type] != NSEventTypeFlagsChanged && [event isARepeat];
        m_isKeypad = isKeypadEvent(event);
        m_isSystemKey = false; // SystemKey is always false on the Mac.

        // Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter.
        if (m_windowsVirtualKeyCode == VK_RETURN) {
            m_text = "\r";
            m_unmodifiedText = "\r";
        }

        // AppKit sets text to "\x7F" for backspace, but the correct KeyboardEvent character code is 8.
        if (m_windowsVirtualKeyCode == VK_BACK) {
            m_text = "\x8";
            m_unmodifiedText = "\x8";
        }

        // Always use 9 for Tab -- we don't want to use AppKit's different character for shift-tab.
        if (m_windowsVirtualKeyCode == VK_TAB) {
            m_text = "\x9";
            m_unmodifiedText = "\x9";
        }

        // Mac specific.
        m_macEvent = event;
    }
};

PlatformKeyboardEvent PlatformEventFactory::createPlatformKeyboardEvent(NSEvent *event)
{
    return PlatformKeyboardEventBuilder(event);
}

} // namespace WebCore

#endif // PLATFORM(MAC)
