/*
 * Copyright (C) 2008 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. ``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
 * 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. 
 */

#if ENABLE(NETSCAPE_PLUGIN_API) && !defined(__LP64__)

#import "WebNetscapePluginEventHandlerCarbon.h"

#import "WebNetscapePluginView.h"
#import "WebKitLogging.h"
#import "WebKitSystemInterface.h"

// Send null events 50 times a second when active, so plug-ins like Flash get high frame rates.
#define NullEventIntervalActive         0.02
#define NullEventIntervalNotActive      0.25

WebNetscapePluginEventHandlerCarbon::WebNetscapePluginEventHandlerCarbon(WebNetscapePluginView* pluginView)
    : WebNetscapePluginEventHandler(pluginView)
    , m_keyEventHandler(0)
    , m_suspendKeyUpEvents(false)
{
}

static void getCarbonEvent(EventRecord* carbonEvent)
{
    carbonEvent->what = nullEvent;
    carbonEvent->message = 0;
    carbonEvent->when = TickCount();
    
    GetGlobalMouse(&carbonEvent->where);
    carbonEvent->where.h = static_cast<short>(carbonEvent->where.h * HIGetScaleFactor());
    carbonEvent->where.v = static_cast<short>(carbonEvent->where.v * HIGetScaleFactor());
    carbonEvent->modifiers = GetCurrentKeyModifiers();
    if (!Button())
        carbonEvent->modifiers |= btnState;
}

static EventModifiers modifiersForEvent(NSEvent *event)
{
    EventModifiers modifiers;
    unsigned int modifierFlags = [event modifierFlags];
    NSEventType eventType = [event type];
    
    modifiers = 0;
    
    if (eventType != NSLeftMouseDown && eventType != NSRightMouseDown)
        modifiers |= btnState;
    
    if (modifierFlags & NSCommandKeyMask)
        modifiers |= cmdKey;
    
    if (modifierFlags & NSShiftKeyMask)
        modifiers |= shiftKey;

    if (modifierFlags & NSAlphaShiftKeyMask)
        modifiers |= alphaLock;

    if (modifierFlags & NSAlternateKeyMask)
        modifiers |= optionKey;

    if (modifierFlags & NSControlKeyMask || eventType == NSRightMouseDown)
        modifiers |= controlKey;
    
    return modifiers;
}

static void getCarbonEvent(EventRecord *carbonEvent, NSEvent *cocoaEvent)
{
    if (WKConvertNSEventToCarbonEvent(carbonEvent, cocoaEvent)) {
        carbonEvent->where.h = static_cast<short>(carbonEvent->where.h * HIGetScaleFactor());
        carbonEvent->where.v = static_cast<short>(carbonEvent->where.v * HIGetScaleFactor());
        return;
    }
    
    NSPoint where = [[cocoaEvent window] convertBaseToScreen:[cocoaEvent locationInWindow]];
        
    carbonEvent->what = nullEvent;
    carbonEvent->message = 0;
    carbonEvent->when = (UInt32)([cocoaEvent timestamp] * 60); // seconds to ticks
    carbonEvent->where.h = (short)where.x;
    carbonEvent->where.v = (short)(NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - where.y);
    carbonEvent->modifiers = modifiersForEvent(cocoaEvent);
}

void WebNetscapePluginEventHandlerCarbon::sendNullEvent()
{
    EventRecord event;
    
    getCarbonEvent(&event);
    
    // Plug-in should not react to cursor position when not active or when a menu is down.
    MenuTrackingData trackingData;
    OSStatus error = GetMenuTrackingData(NULL, &trackingData);
    
    // Plug-in should not react to cursor position when the actual window is not key.
    if (![[m_pluginView window] isKeyWindow] || (error == noErr && trackingData.menu)) {
        // FIXME: Does passing a v and h of -1 really prevent it from reacting to the cursor position?
        event.where.v = -1;
        event.where.h = -1;
    }
    
    sendEvent(&event);
}

void WebNetscapePluginEventHandlerCarbon::drawRect(CGContextRef, const NSRect&)
{
    EventRecord event;
    
    getCarbonEvent(&event);
    event.what = updateEvt;
    WindowRef windowRef = (WindowRef)[[m_pluginView window] windowRef];
    event.message = (unsigned long)windowRef;
    
    BOOL acceptedEvent;
    acceptedEvent = sendEvent(&event);
    
    LOG(PluginEvents, "NPP_HandleEvent(updateEvt): %d", acceptedEvent);
}

void WebNetscapePluginEventHandlerCarbon::mouseDown(NSEvent* theEvent)
{
    EventRecord event;
    
    getCarbonEvent(&event, theEvent);
    event.what = ::mouseDown;
    
    BOOL acceptedEvent;
    acceptedEvent = sendEvent(&event);
    
    LOG(PluginEvents, "NPP_HandleEvent(mouseDown): %d pt.v=%d, pt.h=%d", acceptedEvent, event.where.v, event.where.h);    
}

void WebNetscapePluginEventHandlerCarbon::mouseUp(NSEvent* theEvent)
{
    EventRecord event;
    
    getCarbonEvent(&event, theEvent);
    event.what = ::mouseUp;
    
    BOOL acceptedEvent;
    acceptedEvent = sendEvent(&event);
    
    LOG(PluginEvents, "NPP_HandleEvent(mouseUp): %d pt.v=%d, pt.h=%d", acceptedEvent, event.where.v, event.where.h);    
}

bool WebNetscapePluginEventHandlerCarbon::scrollWheel(NSEvent* theEvent)
{
    return false;
}

void WebNetscapePluginEventHandlerCarbon::mouseEntered(NSEvent* theEvent)
{
    EventRecord event;
    
    getCarbonEvent(&event, theEvent);
    event.what = adjustCursorEvent;
    
    BOOL acceptedEvent;
    acceptedEvent = sendEvent(&event);
    
    LOG(PluginEvents, "NPP_HandleEvent(mouseEntered): %d", acceptedEvent);    
}

void WebNetscapePluginEventHandlerCarbon::mouseExited(NSEvent* theEvent)
{
    EventRecord event;
    
    getCarbonEvent(&event, theEvent);
    event.what = adjustCursorEvent;
    
    BOOL acceptedEvent;
    acceptedEvent = sendEvent(&event);
    
    LOG(PluginEvents, "NPP_HandleEvent(mouseExited): %d", acceptedEvent);    
}

void WebNetscapePluginEventHandlerCarbon::mouseDragged(NSEvent*)
{
}

void WebNetscapePluginEventHandlerCarbon::mouseMoved(NSEvent*)
{
}

void WebNetscapePluginEventHandlerCarbon::keyDown(NSEvent *theEvent)
{
    m_suspendKeyUpEvents = true;
    WKSendKeyEventToTSM(theEvent);
}

void WebNetscapePluginEventHandlerCarbon::syntheticKeyDownWithCommandModifier(int keyCode, char character)
{
    EventRecord event;
    getCarbonEvent(&event);
    
    event.what = ::keyDown;
    event.modifiers |= cmdKey;
    event.message = keyCode << 8 | character;
    sendEvent(&event);
}

static UInt32 keyMessageForEvent(NSEvent *event)
{
    NSData *data = [[event characters] dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(CFStringGetSystemEncoding())];
    if (!data)
        return 0;

    UInt8 characterCode;
    [data getBytes:&characterCode length:1];
    UInt16 keyCode = [event keyCode];
    return keyCode << 8 | characterCode;
}    
    
void WebNetscapePluginEventHandlerCarbon::keyUp(NSEvent* theEvent)
{
    WKSendKeyEventToTSM(theEvent);
    
    // TSM won't send keyUp events so we have to send them ourselves.
    // Only send keyUp events after we receive the TSM callback because this is what plug-in expect from OS 9.
    if (!m_suspendKeyUpEvents) {
        EventRecord event;
        
        getCarbonEvent(&event, theEvent);
        event.what = ::keyUp;
        
        if (event.message == 0)
            event.message = keyMessageForEvent(theEvent);
        
        sendEvent(&event);
    }    
}

void WebNetscapePluginEventHandlerCarbon::flagsChanged(NSEvent*)
{
}

void WebNetscapePluginEventHandlerCarbon::focusChanged(bool hasFocus)
{
    EventRecord event;
    
    getCarbonEvent(&event);
    bool acceptedEvent;
    if (hasFocus) {
        event.what = getFocusEvent;
        acceptedEvent = sendEvent(&event);
        LOG(PluginEvents, "NPP_HandleEvent(getFocusEvent): %d", acceptedEvent);
        installKeyEventHandler();
    } else {
        event.what = loseFocusEvent;
        acceptedEvent = sendEvent(&event);
        LOG(PluginEvents, "NPP_HandleEvent(loseFocusEvent): %d", acceptedEvent);
        removeKeyEventHandler();
    }
}

void WebNetscapePluginEventHandlerCarbon::windowFocusChanged(bool hasFocus)
{
    WindowRef windowRef = (WindowRef)[[m_pluginView window] windowRef];

    SetUserFocusWindow(windowRef);
    
    EventRecord event;
    
    getCarbonEvent(&event);
    event.what = activateEvt;
    event.message = (unsigned long)windowRef;
    if (hasFocus)
        event.modifiers |= activeFlag;
    
    BOOL acceptedEvent;
    acceptedEvent = sendEvent(&event);
    
    LOG(PluginEvents, "NPP_HandleEvent(activateEvent): %d  isActive: %d", acceptedEvent, hasFocus);    
}

OSStatus WebNetscapePluginEventHandlerCarbon::TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *eventHandler)
{    
    EventRef rawKeyEventRef;
    OSStatus status = GetEventParameter(inEvent, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(EventRef), NULL, &rawKeyEventRef);
    if (status != noErr) {
        LOG_ERROR("GetEventParameter failed with error: %d", status);
        return noErr;
    }
    
    // Two-pass read to allocate/extract Mac charCodes
    ByteCount numBytes;    
    status = GetEventParameter(rawKeyEventRef, kEventParamKeyMacCharCodes, typeChar, NULL, 0, &numBytes, NULL);
    if (status != noErr) {
        LOG_ERROR("GetEventParameter failed with error: %d", status);
        return noErr;
    }
    char *buffer = (char *)malloc(numBytes);
    status = GetEventParameter(rawKeyEventRef, kEventParamKeyMacCharCodes, typeChar, NULL, numBytes, NULL, buffer);
    if (status != noErr) {
        LOG_ERROR("GetEventParameter failed with error: %d", status);
        free(buffer);
        return noErr;
    }
    
    EventRef cloneEvent = CopyEvent(rawKeyEventRef);
    unsigned i;
    for (i = 0; i < numBytes; i++) {
        status = SetEventParameter(cloneEvent, kEventParamKeyMacCharCodes, typeChar, 1 /* one char code */, &buffer[i]);
        if (status != noErr) {
            LOG_ERROR("SetEventParameter failed with error: %d", status);
            free(buffer);
            return noErr;
        }
        
        EventRecord eventRec;
        if (ConvertEventRefToEventRecord(cloneEvent, &eventRec)) {
            BOOL acceptedEvent;
            acceptedEvent = static_cast<WebNetscapePluginEventHandlerCarbon*>(eventHandler)->sendEvent(&eventRec);
            
            LOG(PluginEvents, "NPP_HandleEvent(keyDown): %d charCode:%c keyCode:%lu",
                acceptedEvent, (char) (eventRec.message & charCodeMask), (eventRec.message & keyCodeMask));
            
            // We originally thought that if the plug-in didn't accept this event,
            // we should pass it along so that keyboard scrolling, for example, will work.
            // In practice, this is not a good idea, because plug-ins tend to eat the event but return false.
            // MacIE handles each key event twice because of this, but we will emulate the other browsers instead.
        }
    }
    ReleaseEvent(cloneEvent);
    
    free(buffer);
    
    return noErr;
}

void WebNetscapePluginEventHandlerCarbon::installKeyEventHandler()
{
    static const EventTypeSpec sTSMEvents[] =
    {
        { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }
    };
    
    if (!m_keyEventHandler) {
        InstallEventHandler(GetWindowEventTarget((WindowRef)[[m_pluginView window] windowRef]),
                            NewEventHandlerUPP(TSMEventHandler),
                            GetEventTypeCount(sTSMEvents),
                            sTSMEvents,
                            this,
                            &m_keyEventHandler);
    }
}

void WebNetscapePluginEventHandlerCarbon::removeKeyEventHandler()
{
    if (m_keyEventHandler) {
        RemoveEventHandler(m_keyEventHandler);
        m_keyEventHandler = 0;
    }    
}

void WebNetscapePluginEventHandlerCarbon::nullEventTimerFired(CFRunLoopTimerRef timerRef, void *context)
{
    static_cast<WebNetscapePluginEventHandlerCarbon*>(context)->sendNullEvent();
}

void WebNetscapePluginEventHandlerCarbon::startTimers(bool throttleTimers)
{
    ASSERT(!m_nullEventTimer);
    
    CFTimeInterval interval = !throttleTimers ? NullEventIntervalActive : NullEventIntervalNotActive;    
    
    CFRunLoopTimerContext context = { 0, this, NULL, NULL, NULL };
    m_nullEventTimer.adoptCF(CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent() + interval, interval,
                                                   0, 0, nullEventTimerFired, &context));
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_nullEventTimer.get(), kCFRunLoopDefaultMode);
}

void WebNetscapePluginEventHandlerCarbon::stopTimers()
{
    if (!m_nullEventTimer)
        return;
    
    CFRunLoopTimerInvalidate(m_nullEventTimer.get());
    m_nullEventTimer = 0;
}

void* WebNetscapePluginEventHandlerCarbon::platformWindow(NSWindow* window)
{
    return [window windowRef];
}

bool WebNetscapePluginEventHandlerCarbon::sendEvent(EventRecord* event)
{
    // If at any point the user clicks or presses a key from within a plugin, set the 
    // currentEventIsUserGesture flag to true. This is important to differentiate legitimate 
    // window.open() calls;  we still want to allow those.  See rdar://problem/4010765
    if (event->what == ::mouseDown || event->what == ::keyDown || event->what == ::mouseUp || event->what == ::autoKey)
        m_currentEventIsUserGesture = true;
    
    m_suspendKeyUpEvents = false; 

    bool result = [m_pluginView sendEvent:event isDrawRect:event->what == updateEvt];
    
    m_currentEventIsUserGesture = false;
    
    return result;
}

#endif // ENABLE(NETSCAPE_PLUGIN_API) && !defined(__LP64__)
