/*
 * MACDRV Cocoa clipboard code
 *
 * Copyright 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 "macdrv_cocoa.h"
#import "cocoa_app.h"
#import "cocoa_event.h"
#import "cocoa_window.h"


static int owned_change_count = -1;

static NSArray* BitmapOutputTypes;
static NSDictionary* BitmapOutputTypeMap;
static dispatch_once_t BitmapOutputTypesInitOnce;

static NSString* const OwnershipSentinel = @"org.winehq.wine.winemac.pasteboard-ownership-sentinel";


/***********************************************************************
 *              macdrv_is_pasteboard_owner
 */
int macdrv_is_pasteboard_owner(macdrv_window w)
{
    __block int ret;
    WineWindow* window = (WineWindow*)w;

    OnMainThread(^{
        NSPasteboard* pb = [NSPasteboard generalPasteboard];
        ret = ([pb changeCount] == owned_change_count);

        [window.queue discardEventsMatchingMask:event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP)
                                      forWindow:window];
    });

    return ret;
}


/***********************************************************************
 *              macdrv_copy_pasteboard_types
 *
 * Returns an array of UTI strings for the types of data available on
 * the pasteboard, or NULL on error.  The caller is responsible for
 * releasing the returned array with CFRelease().
 */
CFArrayRef macdrv_copy_pasteboard_types(CFTypeRef pasteboard)
{
    NSPasteboard* pb = (NSPasteboard*)pasteboard;
    __block CFArrayRef ret = NULL;
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    dispatch_once(&BitmapOutputTypesInitOnce, ^{
        NSArray* bitmapFileTypes = [NSArray arrayWithObjects:
                                    [NSNumber numberWithUnsignedInteger:NSTIFFFileType],
                                    [NSNumber numberWithUnsignedInteger:NSPNGFileType],
                                    [NSNumber numberWithUnsignedInteger:NSBMPFileType],
                                    [NSNumber numberWithUnsignedInteger:NSGIFFileType],
                                    [NSNumber numberWithUnsignedInteger:NSJPEGFileType],
                                    nil];

        BitmapOutputTypes = [[NSArray alloc] initWithObjects:@"public.tiff", @"public.png",
                             @"com.microsoft.bmp", @"com.compuserve.gif", @"public.jpeg", nil];

        BitmapOutputTypeMap = [[NSDictionary alloc] initWithObjects:bitmapFileTypes
                                                            forKeys:BitmapOutputTypes];
    });

    OnMainThread(^{
        @try
        {
            NSPasteboard* local_pb = pb;
            NSArray* types;

            if (!local_pb) local_pb = [NSPasteboard generalPasteboard];
            types = [local_pb types];

            // If there are any types understood by NSBitmapImageRep, then we
            // can offer all of the types that it can output, too.  For example,
            // if TIFF is on the pasteboard, we can offer PNG, BMP, etc. to the
            // Windows program.  We'll convert on demand.
            if ([types firstObjectCommonWithArray:[NSBitmapImageRep imageTypes]] ||
                [types firstObjectCommonWithArray:[NSBitmapImageRep imagePasteboardTypes]])
            {
                NSMutableArray* newTypes = [BitmapOutputTypes mutableCopy];
                [newTypes removeObjectsInArray:types];
                types = [types arrayByAddingObjectsFromArray:newTypes];
                [newTypes release];
            }

            ret = (CFArrayRef)[types copy];
        }
        @catch (id e)
        {
            ERR(@"Exception discarded while copying pasteboard types: %@\n", e);
        }
    });

    [pool release];
    return ret;
}


/***********************************************************************
 *              macdrv_copy_pasteboard_data
 *
 * Returns the pasteboard data for a specified type, or NULL on error or
 * if there's no such type on the pasteboard.  The caller is responsible
 * for releasing the returned data object with CFRelease().
 */
CFDataRef macdrv_copy_pasteboard_data(CFTypeRef pasteboard, CFStringRef type)
{
    NSPasteboard* pb = (NSPasteboard*)pasteboard;
    __block NSData* ret = nil;

    OnMainThread(^{
        @try
        {
            NSPasteboard* local_pb = pb;
            if (!local_pb) local_pb = [NSPasteboard generalPasteboard];
            if ([local_pb availableTypeFromArray:[NSArray arrayWithObject:(NSString*)type]])
                ret = [[local_pb dataForType:(NSString*)type] copy];
            else
            {
                NSNumber* bitmapType = [BitmapOutputTypeMap objectForKey:(NSString*)type];
                if (bitmapType)
                {
                    NSArray* reps = [NSBitmapImageRep imageRepsWithPasteboard:local_pb];
                    ret = [NSBitmapImageRep representationOfImageRepsInArray:reps
                                                                   usingType:[bitmapType unsignedIntegerValue]
                                                                  properties:nil];
                    ret = [ret copy];
                }
            }
        }
        @catch (id e)
        {
            ERR(@"Exception discarded while copying pasteboard types: %@\n", e);
        }
    });

    return (CFDataRef)ret;
}


/***********************************************************************
 *              macdrv_clear_pasteboard
 *
 * Takes ownership of the Mac pasteboard and clears it of all data types.
 */
void macdrv_clear_pasteboard(macdrv_window w)
{
    WineWindow* window = (WineWindow*)w;

    OnMainThread(^{
        @try
        {
            NSPasteboard* pb = [NSPasteboard generalPasteboard];
            owned_change_count = [pb declareTypes:[NSArray arrayWithObject:OwnershipSentinel]
                                            owner:window];
            [window.queue discardEventsMatchingMask:event_mask_for_type(LOST_PASTEBOARD_OWNERSHIP)
                                          forWindow:window];
        }
        @catch (id e)
        {
            ERR(@"Exception discarded while clearing pasteboard: %@\n", e);
        }
    });
}


/***********************************************************************
 *              macdrv_set_pasteboard_data
 *
 * Sets the pasteboard data for a specified type.  Replaces any data of
 * that type already on the pasteboard.  If data is NULL, promises the
 * type.
 *
 * Returns 0 on error, non-zero on success.
 */
int macdrv_set_pasteboard_data(CFStringRef type, CFDataRef data, macdrv_window w)
{
    __block int ret = 0;
    WineWindow* window = (WineWindow*)w;

    OnMainThread(^{
        @try
        {
            NSPasteboard* pb = [NSPasteboard generalPasteboard];
            NSInteger change_count = [pb addTypes:[NSArray arrayWithObject:(NSString*)type]
                                            owner:window];
            if (change_count)
            {
                owned_change_count = change_count;
                if (data)
                    ret = [pb setData:(NSData*)data forType:(NSString*)type];
                else
                    ret = 1;
            }
        }
        @catch (id e)
        {
            ERR(@"Exception discarded while copying pasteboard types: %@\n", e);
        }
    });

    return ret;
}
