/*
 * MACDRV Cocoa event queue code
 *
 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <libkern/OSAtomic.h>
#import <Carbon/Carbon.h>

#include "macdrv_cocoa.h"
#import "cocoa_event.h"
#import "cocoa_app.h"
#import "cocoa_window.h"


static NSString* const WineEventQueueThreadDictionaryKey = @"WineEventQueueThreadDictionaryKey";

static NSString* const WineHotKeyMacIDKey       = @"macID";
static NSString* const WineHotKeyVkeyKey        = @"vkey";
static NSString* const WineHotKeyModFlagsKey    = @"modFlags";
static NSString* const WineHotKeyKeyCodeKey     = @"keyCode";
static NSString* const WineHotKeyCarbonRefKey   = @"hotKeyRef";
static const OSType WineHotKeySignature = 'Wine';


@interface MacDrvEvent : NSObject
{
@public
    macdrv_event* event;
}

    - (id) initWithEvent:(macdrv_event*)event;

@end

@implementation MacDrvEvent

    - (id) initWithEvent:(macdrv_event*)inEvent
    {
        self = [super init];
        if (self)
        {
            event = macdrv_retain_event(inEvent);
        }
        return self;
    }

    - (void) dealloc
    {
        if (event) macdrv_release_event(event);
        [super dealloc];
    }

@end


@implementation WineEventQueue

    - (id) init
    {
        [self doesNotRecognizeSelector:_cmd];
        [self release];
        return nil;
    }

    - (id) initWithEventHandler:(macdrv_event_handler)handler
    {
        NSParameterAssert(handler != nil);

        self = [super init];
        if (self != nil)
        {
            struct kevent kev;
            int rc;

            fds[0] = fds[1] = kq = -1;

            event_handler = handler;
            events = [[NSMutableArray alloc] init];
            eventsLock = [[NSLock alloc] init];

            if (!events || !eventsLock)
            {
                [self release];
                return nil;
            }

            if (pipe(fds) ||
                fcntl(fds[0], F_SETFD, 1) == -1 ||
                fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
                fcntl(fds[1], F_SETFD, 1) == -1 ||
                fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1)
            {
                [self release];
                return nil;
            }

            kq = kqueue();
            if (kq < 0)
            {
                [self release];
                return nil;
            }

            EV_SET(&kev, fds[0], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
            do
            {
                rc = kevent(kq, &kev, 1, NULL, 0, NULL);
            } while (rc == -1 && errno == EINTR);
            if (rc == -1)
            {
                [self release];
                return nil;
            }
        }
        return self;
    }

    - (void) dealloc
    {
        NSNumber* hotKeyMacID;

        for (hotKeyMacID in hotKeysByMacID)
        {
            NSDictionary* hotKeyDict = [hotKeysByMacID objectForKey:hotKeyMacID];
            EventHotKeyRef hotKeyRef = [[hotKeyDict objectForKey:WineHotKeyCarbonRefKey] pointerValue];
            UnregisterEventHotKey(hotKeyRef);
        }
        [hotKeysByMacID release];
        [hotKeysByWinID release];
        [events release];
        [eventsLock release];

        if (kq != -1) close(kq);
        if (fds[0] != -1) close(fds[0]);
        if (fds[1] != -1) close(fds[1]);

        [super dealloc];
    }

    - (void) signalEventAvailable
    {
        char junk = 1;
        int rc;

        do
        {
            rc = write(fds[1], &junk, 1);
        } while (rc < 0 && errno == EINTR);

        if (rc < 0 && errno != EAGAIN)
            ERR(@"%@: got error writing to event queue signaling pipe: %s\n", self, strerror(errno));
    }

    - (void) postEventObject:(MacDrvEvent*)event
    {
        NSIndexSet* indexes;
        MacDrvEvent* lastEvent;

        [eventsLock lock];

        indexes = [events indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
            return ((MacDrvEvent*)obj)->event->deliver <= 0;
        }];
        [events removeObjectsAtIndexes:indexes];

        if ((event->event->type == MOUSE_MOVED ||
             event->event->type == MOUSE_MOVED_ABSOLUTE) &&
            event->event->deliver == INT_MAX &&
            (lastEvent = [events lastObject]) &&
            (lastEvent->event->type == MOUSE_MOVED ||
             lastEvent->event->type == MOUSE_MOVED_ABSOLUTE) &&
            lastEvent->event->deliver == INT_MAX &&
            lastEvent->event->window == event->event->window &&
            lastEvent->event->mouse_moved.drag == event->event->mouse_moved.drag)
        {
            if (event->event->type == MOUSE_MOVED)
            {
                lastEvent->event->mouse_moved.x += event->event->mouse_moved.x;
                lastEvent->event->mouse_moved.y += event->event->mouse_moved.y;
            }
            else
            {
                lastEvent->event->type = MOUSE_MOVED_ABSOLUTE;
                lastEvent->event->mouse_moved.x = event->event->mouse_moved.x;
                lastEvent->event->mouse_moved.y = event->event->mouse_moved.y;
            }

            lastEvent->event->mouse_moved.time_ms = event->event->mouse_moved.time_ms;
        }
        else
            [events addObject:event];

        [eventsLock unlock];

        [self signalEventAvailable];
    }

    - (void) postEvent:(macdrv_event*)inEvent
    {
        MacDrvEvent* event = [[MacDrvEvent alloc] initWithEvent:inEvent];
        [self postEventObject:event];
        [event release];
    }

    - (MacDrvEvent*) getEventMatchingMask:(macdrv_event_mask)mask
    {
        char buf[512];
        int rc;
        NSUInteger index;
        MacDrvEvent* ret = nil;

        /* Clear the pipe which signals there are pending events. */
        do
        {
            rc = read(fds[0], buf, sizeof(buf));
        } while (rc > 0 || (rc < 0 && errno == EINTR));
        if (rc == 0 || (rc < 0 && errno != EAGAIN))
        {
            if (rc == 0)
                ERR(@"%@: event queue signaling pipe unexpectedly closed\n", self);
            else
                ERR(@"%@: got error reading from event queue signaling pipe: %s\n", self, strerror(errno));
            return nil;
        }

        [eventsLock lock];

        index = 0;
        while (index < [events count])
        {
            MacDrvEvent* event = [events objectAtIndex:index];
            if (event_mask_for_type(event->event->type) & mask)
            {
                [[event retain] autorelease];
                [events removeObjectAtIndex:index];

                if (event->event->deliver == INT_MAX ||
                    OSAtomicDecrement32Barrier(&event->event->deliver) >= 0)
                {
                    ret = event;
                    break;
                }
            }
            else
                index++;
        }

        [eventsLock unlock];
        return ret;
    }

    - (void) discardEventsPassingTest:(BOOL (^)(macdrv_event* event))block
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        NSIndexSet* indexes;

        [eventsLock lock];

        indexes = [events indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
            MacDrvEvent* event = obj;
            return block(event->event);
        }];

        [events removeObjectsAtIndexes:indexes];

        [eventsLock unlock];

        [pool release];
    }

    - (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)window
    {
        [self discardEventsPassingTest:^BOOL (macdrv_event* event){
            return ((event_mask_for_type(event->type) & mask) &&
                    (!window || event->window == (macdrv_window)window));
        }];
    }

    - (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout processEvents:(BOOL)processEvents
    {
        macdrv_event* event;
        NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
        BOOL timedout;

        event = macdrv_create_event(QUERY_EVENT, (WineWindow*)query->window);
        event->query_event.query = macdrv_retain_query(query);
        query->done = FALSE;

        [self postEvent:event];
        macdrv_release_event(event);
        timedout = ![[WineApplicationController sharedController] waitUntilQueryDone:&query->done
                                                                             timeout:timeoutDate
                                                                       processEvents:processEvents];
        return !timedout && query->status;
    }

    - (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout
    {
        return [self query:query timeout:timeout processEvents:FALSE];
    }

    - (void) resetMouseEventPositions:(CGPoint)pos
    {
        MacDrvEvent* event;

        [eventsLock lock];

        for (event in events)
        {
            if (event->event->type == MOUSE_BUTTON)
            {
                event->event->mouse_button.x = pos.x;
                event->event->mouse_button.y = pos.y;
            }
            else if (event->event->type == MOUSE_SCROLL)
            {
                event->event->mouse_scroll.x = pos.x;
                event->event->mouse_scroll.y = pos.y;
            }
        }

        [eventsLock unlock];
    }

    - (BOOL) postHotKeyEvent:(UInt32)hotKeyNumber time:(double)time
    {
        NSDictionary* hotKeyDict = [hotKeysByMacID objectForKey:[NSNumber numberWithUnsignedInt:hotKeyNumber]];
        if (hotKeyDict)
        {
            macdrv_event* event;

            event = macdrv_create_event(HOTKEY_PRESS, nil);
            event->hotkey_press.vkey        = [[hotKeyDict objectForKey:WineHotKeyVkeyKey] unsignedIntValue];
            event->hotkey_press.mod_flags   = [[hotKeyDict objectForKey:WineHotKeyModFlagsKey] unsignedIntValue];
            event->hotkey_press.keycode     = [[hotKeyDict objectForKey:WineHotKeyKeyCodeKey] unsignedIntValue];
            event->hotkey_press.time_ms     = [[WineApplicationController sharedController] ticksForEventTime:time];

            [self postEvent:event];

            macdrv_release_event(event);
        }

        return hotKeyDict != nil;
    }

    static OSStatus HotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
    {
        WineEventQueue* self = userData;
        OSStatus status;
        EventHotKeyID hotKeyID;

        status = GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL,
                                   sizeof(hotKeyID), NULL, &hotKeyID);
        if (status == noErr)
        {
            if (hotKeyID.signature != WineHotKeySignature ||
                ![self postHotKeyEvent:hotKeyID.id time:GetEventTime(theEvent)])
                status = eventNotHandledErr;
        }

        return status;
    }

    - (void) unregisterHotKey:(unsigned int)vkey modFlags:(unsigned int)modFlags
    {
        NSNumber* vkeyNumber = [NSNumber numberWithUnsignedInt:vkey];
        NSNumber* modFlagsNumber = [NSNumber numberWithUnsignedInt:modFlags];
        NSArray* winIDPair = [NSArray arrayWithObjects:vkeyNumber, modFlagsNumber, nil];
        NSDictionary* hotKeyDict = [hotKeysByWinID objectForKey:winIDPair];
        if (hotKeyDict)
        {
            EventHotKeyRef hotKeyRef = [[hotKeyDict objectForKey:WineHotKeyCarbonRefKey] pointerValue];
            NSNumber* macID = [hotKeyDict objectForKey:WineHotKeyMacIDKey];

            UnregisterEventHotKey(hotKeyRef);
            [hotKeysByMacID removeObjectForKey:macID];
            [hotKeysByWinID removeObjectForKey:winIDPair];
        }
    }

    - (int) registerHotKey:(UInt32)keyCode modifiers:(UInt32)modifiers vkey:(unsigned int)vkey modFlags:(unsigned int)modFlags
    {
        static EventHandlerRef handler;
        static UInt32 hotKeyNumber;
        OSStatus status;
        NSNumber* vkeyNumber;
        NSNumber* modFlagsNumber;
        NSArray* winIDPair;
        EventHotKeyID hotKeyID;
        EventHotKeyRef hotKeyRef;
        NSNumber* macIDNumber;
        NSDictionary* hotKeyDict;

        if (!handler)
        {
            EventTypeSpec eventType = { kEventClassKeyboard, kEventHotKeyPressed };
            status = InstallApplicationEventHandler(HotKeyHandler, 1, &eventType, self, &handler);
            if (status != noErr)
            {
                ERR(@"InstallApplicationEventHandler() failed: %d\n", status);
                handler = NULL;
                return MACDRV_HOTKEY_FAILURE;
            }
        }

        if (!hotKeysByMacID && !(hotKeysByMacID = [[NSMutableDictionary alloc] init]))
            return MACDRV_HOTKEY_FAILURE;
        if (!hotKeysByWinID && !(hotKeysByWinID = [[NSMutableDictionary alloc] init]))
            return MACDRV_HOTKEY_FAILURE;

        vkeyNumber = [NSNumber numberWithUnsignedInt:vkey];
        modFlagsNumber = [NSNumber numberWithUnsignedInt:modFlags];
        winIDPair = [NSArray arrayWithObjects:vkeyNumber, modFlagsNumber, nil];
        if ([hotKeysByWinID objectForKey:winIDPair])
            return MACDRV_HOTKEY_ALREADY_REGISTERED;

        hotKeyID.signature  = WineHotKeySignature;
        hotKeyID.id         = hotKeyNumber++;

        status = RegisterEventHotKey(keyCode, modifiers, hotKeyID, GetApplicationEventTarget(),
                                     kEventHotKeyExclusive, &hotKeyRef);
        if (status == eventHotKeyExistsErr)
            return MACDRV_HOTKEY_ALREADY_REGISTERED;
        if (status != noErr)
        {
            ERR(@"RegisterEventHotKey() failed: %d\n", status);
            return MACDRV_HOTKEY_FAILURE;
        }

        macIDNumber = [NSNumber numberWithUnsignedInt:hotKeyID.id];
        hotKeyDict = [NSDictionary dictionaryWithObjectsAndKeys:
                      macIDNumber, WineHotKeyMacIDKey,
                      vkeyNumber, WineHotKeyVkeyKey,
                      modFlagsNumber, WineHotKeyModFlagsKey,
                      [NSNumber numberWithUnsignedInt:keyCode], WineHotKeyKeyCodeKey,
                      [NSValue valueWithPointer:hotKeyRef], WineHotKeyCarbonRefKey,
                      nil];
        [hotKeysByMacID setObject:hotKeyDict forKey:macIDNumber];
        [hotKeysByWinID setObject:hotKeyDict forKey:winIDPair];

        return MACDRV_HOTKEY_SUCCESS;
    }


/***********************************************************************
 *              OnMainThread
 *
 * Run a block on the main thread synchronously.
 */
void OnMainThread(dispatch_block_t block)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];
    WineEventQueue* queue = [threadDict objectForKey:WineEventQueueThreadDictionaryKey];
    dispatch_semaphore_t semaphore;
    __block BOOL finished;

    if (!queue)
    {
        semaphore = dispatch_semaphore_create(0);
        dispatch_retain(semaphore);
    }

    finished = FALSE;
    OnMainThreadAsync(^{
        block();
        finished = TRUE;
        if (queue)
            [queue signalEventAvailable];
        else
        {
            dispatch_semaphore_signal(semaphore);
            dispatch_release(semaphore);
        }
    });

    if (queue)
    {
        while (!finished)
        {
            MacDrvEvent* macDrvEvent;
            struct kevent kev;

            while (!finished &&
                   (macDrvEvent = [queue getEventMatchingMask:event_mask_for_type(QUERY_EVENT)]))
            {
                queue->event_handler(macDrvEvent->event);
            }

            if (!finished)
            {
                [pool release];
                pool = [[NSAutoreleasePool alloc] init];

                kevent(queue->kq, NULL, 0, &kev, 1, NULL);
            }
        }
    }
    else
    {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_release(semaphore);
    }

    [pool release];
}


/***********************************************************************
 *              macdrv_create_event_queue
 *
 * Register this thread with the application on the main thread, and set
 * up an event queue on which it can deliver events to this thread.
 */
macdrv_event_queue macdrv_create_event_queue(macdrv_event_handler handler)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];

    WineEventQueue* queue = [threadDict objectForKey:WineEventQueueThreadDictionaryKey];
    if (!queue)
    {
        queue = [[[WineEventQueue alloc] initWithEventHandler:handler] autorelease];
        if (queue)
        {
            if ([[WineApplicationController sharedController] registerEventQueue:queue])
                [threadDict setObject:queue forKey:WineEventQueueThreadDictionaryKey];
            else
                queue = nil;
        }
    }

    [pool release];
    return (macdrv_event_queue)queue;
}

/***********************************************************************
 *              macdrv_destroy_event_queue
 *
 * Tell the application that this thread is exiting and destroy the
 * associated event queue.
 */
void macdrv_destroy_event_queue(macdrv_event_queue queue)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    WineEventQueue* q = (WineEventQueue*)queue;
    NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];

    [[WineApplicationController sharedController] unregisterEventQueue:q];
    [threadDict removeObjectForKey:WineEventQueueThreadDictionaryKey];

    [pool release];
}

/***********************************************************************
 *              macdrv_get_event_queue_fd
 *
 * Get the file descriptor whose readability signals that there are
 * events on the event queue.
 */
int macdrv_get_event_queue_fd(macdrv_event_queue queue)
{
    WineEventQueue* q = (WineEventQueue*)queue;
    return q->fds[0];
}

/***********************************************************************
 *              macdrv_copy_event_from_queue
 *
 * Pull an event matching the event mask from the event queue and store
 * it in the event record pointed to by the event parameter.  If a
 * matching event was found, return non-zero; otherwise, return 0.
 *
 * The caller is responsible for calling macdrv_release_event on any
 * event returned by this function.
 */
int macdrv_copy_event_from_queue(macdrv_event_queue queue,
        macdrv_event_mask mask, macdrv_event **event)
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    WineEventQueue* q = (WineEventQueue*)queue;

    MacDrvEvent* macDrvEvent = [q getEventMatchingMask:mask];
    if (macDrvEvent)
        *event = macdrv_retain_event(macDrvEvent->event);

    [pool release];
    return (macDrvEvent != nil);
}

/***********************************************************************
 *              macdrv_create_event
 */
macdrv_event* macdrv_create_event(int type, WineWindow* window)
{
    macdrv_event *event;

    event = calloc(1, sizeof(*event));
    event->refs = 1;
    event->deliver = INT_MAX;
    event->type = type;
    event->window = (macdrv_window)[window retain];
    return event;
}

/***********************************************************************
 *              macdrv_retain_event
 */
macdrv_event* macdrv_retain_event(macdrv_event *event)
{
    OSAtomicIncrement32Barrier(&event->refs);
    return event;
}

/***********************************************************************
 *              macdrv_release_event
 *
 * Decrements the reference count of an event.  If the count falls to
 * zero, cleans up any resources, such as allocated memory or retained
 * objects, held by the event and deallocates it
 */
void macdrv_release_event(macdrv_event *event)
{
    if (OSAtomicDecrement32Barrier(&event->refs) <= 0)
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        switch (event->type)
        {
            case IM_SET_TEXT:
                if (event->im_set_text.text)
                    CFRelease(event->im_set_text.text);
                break;
            case KEYBOARD_CHANGED:
                CFRelease(event->keyboard_changed.uchr);
                CFRelease(event->keyboard_changed.input_source);
                break;
            case QUERY_EVENT:
                macdrv_release_query(event->query_event.query);
                break;
            case WINDOW_GOT_FOCUS:
                [(NSMutableSet*)event->window_got_focus.tried_windows release];
                break;
        }

        [(WineWindow*)event->window release];
        free(event);

        [pool release];
    }
}

/***********************************************************************
 *              macdrv_create_query
 */
macdrv_query* macdrv_create_query(void)
{
    macdrv_query *query;

    query = calloc(1, sizeof(*query));
    query->refs = 1;
    return query;
}

/***********************************************************************
 *              macdrv_retain_query
 */
macdrv_query* macdrv_retain_query(macdrv_query *query)
{
    OSAtomicIncrement32Barrier(&query->refs);
    return query;
}

/***********************************************************************
 *              macdrv_release_query
 */
void macdrv_release_query(macdrv_query *query)
{
    if (OSAtomicDecrement32Barrier(&query->refs) <= 0)
    {
        switch (query->type)
        {
            case QUERY_DRAG_OPERATION:
                if (query->drag_operation.pasteboard)
                    CFRelease(query->drag_operation.pasteboard);
                break;
            case QUERY_DRAG_DROP:
                if (query->drag_drop.pasteboard)
                    CFRelease(query->drag_drop.pasteboard);
                break;
            case QUERY_PASTEBOARD_DATA:
                if (query->pasteboard_data.type)
                    CFRelease(query->pasteboard_data.type);
                break;
        }
        [(WineWindow*)query->window release];
        free(query);
    }
}

/***********************************************************************
 *              macdrv_set_query_done
 */
void macdrv_set_query_done(macdrv_query *query)
{
    macdrv_retain_query(query);

    OnMainThreadAsync(^{
        NSEvent* event;

        query->done = TRUE;
        macdrv_release_query(query);

        event = [NSEvent otherEventWithType:NSApplicationDefined
                                   location:NSZeroPoint
                              modifierFlags:0
                                  timestamp:[[NSProcessInfo processInfo] systemUptime]
                               windowNumber:0
                                    context:nil
                                    subtype:WineApplicationEventWakeQuery
                                      data1:0
                                      data2:0];
        [NSApp postEvent:event atStart:TRUE];
    });
}

@end


/***********************************************************************
 *              macdrv_register_hot_key
 */
int macdrv_register_hot_key(macdrv_event_queue q, unsigned int vkey, unsigned int mod_flags,
                            unsigned int keycode, unsigned int modifiers)
{
    WineEventQueue* queue = (WineEventQueue*)q;
    __block int ret;

    OnMainThread(^{
        ret = [queue registerHotKey:keycode modifiers:modifiers vkey:vkey modFlags:mod_flags];
    });

    return ret;
}


/***********************************************************************
 *              macdrv_unregister_hot_key
 */
void macdrv_unregister_hot_key(macdrv_event_queue q, unsigned int vkey, unsigned int mod_flags)
{
    WineEventQueue* queue = (WineEventQueue*)q;

    OnMainThreadAsync(^{
        [queue unregisterHotKey:vkey modFlags:mod_flags];
    });
}
