/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */

// http://developer.apple.com/library/mac/#documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html%23//apple_ref/doc/uid/TP40009259-SW1
// /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/UTCoreTypes.h

#import "common.h"

#import "GlassPasteboard.h"
#import "GlassMacros.h"
#import "GlassDragSource.h"

#import "com_sun_glass_ui_mac_MacPasteboard.h"
#import "com_sun_glass_ui_Clipboard.h"

//#define VERBOSE
#ifndef VERBOSE
    #define LOG(MSG, ...)
#else
    #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
#endif

#define RAW_IMAGE_MIME @"application.x-java-rawimage"

static inline void DumpPasteboard(NSPasteboard *pasteboard)
{
    NSLog(@"\n");
    NSLog(@"DumpPasteboard");
    
    NSArray *items = [pasteboard pasteboardItems];
    if ([items count] > 0)
    {
        NSLog(@"---- [items count]: %d", (int)[items count]);
        for (int i=0; i<[items count]; i++)
        {
            NSPasteboardItem *item = [items objectAtIndex:i];
            NSArray *types = [item types];
            for (int j=0; j<[types count]; j++)
            {
                NSString *type = [types objectAtIndex:j];
                NSLog(@"--------- type: %@", type);
                
                NSUInteger length = 128;
                
                NSData *data = [item dataForType:type];
                NSString *string = [item stringForType:type];
                id representation = nil;
                if (string != nil)
                {
                    length = MIN(length, [string length]);
                    representation = [string substringToIndex:length];
                }
                else
                {
                    length = MIN(length, [data length]);
                    representation = [data subdataWithRange:NSMakeRange(0, length)];
                }
                NSLog(@"------------- data: %p [length: %d bytes] [first %d bytes rep: %@]", data, (int)[data length], (int)length, representation);
            }
        }
    }
    
    NSLog(@"\n");
}

static inline jbyteArray ByteArrayFromPixels(JNIEnv *env, void *data, int width, int height)
{
    jbyteArray javaArray = NULL;
    
    if ((data != NULL) && (width > 0) && (height > 0))
    {
        javaArray = (*env)->NewByteArray(env, 4*(width*height) + 4*(1+1));
        GLASS_CHECK_EXCEPTION(env);
        
        if (javaArray != NULL)
        {
            jbyte *w = (jbyte*)&width;
            (*env)->SetByteArrayRegion(env, javaArray, 0, 1, (jbyte *)&w[3]);
            (*env)->SetByteArrayRegion(env, javaArray, 1, 1, (jbyte *)&w[2]);
            (*env)->SetByteArrayRegion(env, javaArray, 2, 1, (jbyte *)&w[1]);
            (*env)->SetByteArrayRegion(env, javaArray, 3, 1, (jbyte *)&w[0]);
            
            jbyte *h = (jbyte*)&height;
            (*env)->SetByteArrayRegion(env, javaArray, 4, 1, (jbyte *)&h[3]);
            (*env)->SetByteArrayRegion(env, javaArray, 5, 1, (jbyte *)&h[2]);
            (*env)->SetByteArrayRegion(env, javaArray, 6, 1, (jbyte *)&h[1]);
            (*env)->SetByteArrayRegion(env, javaArray, 7, 1, (jbyte *)&h[0]);
            
            (*env)->SetByteArrayRegion(env, javaArray, 8, 4*(width*height), (jbyte *)data);
        }
    }
    
    return javaArray;
}

static inline jbyteArray ByteArrayFromNSData(JNIEnv *env, NSData *data)
{
    jbyteArray javaArray = NULL;
    
    if (data != nil)
    {
        javaArray = (*env)->NewByteArray(env, [data length]);
        GLASS_CHECK_EXCEPTION(env);
        
        if (javaArray != NULL)
        {
            (*env)->SetByteArrayRegion(env, javaArray, 0, [data length], (jbyte *)[data bytes]);
        }
    }
    
    return javaArray;
}

static inline void SetNSPasteboardItemValueForUtf(JNIEnv *env, NSPasteboardItem *item, jobject jValue, NSString *utf)
{
    BOOL isString = NO;
    if ([utf isEqualToString:NSPasteboardTypeString] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:NSPasteboardTypePDF] == YES)
    {
        isString = YES;
    }
    if ([utf isEqualToString:NSPasteboardTypeRTF] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:NSPasteboardTypeRTFD] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:NSPasteboardTypeHTML] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:NSPasteboardTypeTabularText] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:NSPasteboardTypeMultipleTextSelection] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:NSPasteboardTypeFindPanelSearchOptions] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:(NSString*)kUTTypeURL] == YES)
    {
        isString = YES;
    }
    else if ([utf isEqualToString:(NSString*)kUTTypeFileURL] == YES)
    {
        isString = YES;
    }
    
    if (isString == YES)
    {
        NSString *string = nil;
        {
            const jchar *chars = (*env)->GetStringChars(env, jValue, NULL);
            string = [NSString stringWithCharacters:(UniChar *)chars length:(*env)->GetStringLength(env, jValue)];
            (*env)->ReleaseStringChars(env, jValue, chars);
        }
        [item setString:string forType:utf];
        //NSLog(@"		SetValue(string): %@, ForUtf: %@", string, utf);
    }
    else
    {
        if ([utf isEqualToString:RAW_IMAGE_MIME] == YES)
        {
            NSImage *image = NULL;
            (*env)->CallVoidMethod(env, jValue, jPixelsAttachData, ptr_to_jlong(&image));
            if (image != NULL)
            {
                NSData *data = [image TIFFRepresentation];
                [item setData:data forType:NSPasteboardTypeTIFF];
                //NSLog(@"		setData: %p, ForUtf: %@", data, utf);
            }
        }
        else
        {
            NSData *data = nil;
            {
                jbyte *bytes = (*env)->GetByteArrayElements(env, jValue, NULL);
                data = [NSData dataWithBytes:bytes length:(*env)->GetArrayLength(env, jValue)];
                (*env)->ReleaseByteArrayElements(env, jValue, bytes, 0);
            }
            [item setData:data forType:utf];
            //NSLog(@"		SetValue(data): %p, ForUtf: %@", data, utf);
        }
    }
    GLASS_CHECK_EXCEPTION(env);
}

static inline NSPasteboardItem *NSPasteboardItemFromArray(JNIEnv *env, jobjectArray jArray)
{
    NSPasteboardItem *item = [[[NSPasteboardItem alloc] init] autorelease];
    {
        jsize repsCount = (*env)->GetArrayLength(env, jArray);
        //NSLog(@"	NSPasteboardItemFromArray repsCount: %d", repsCount);
        if (repsCount > 0)
        {
            for (int i=0; i<repsCount; i++)
            {
                jobjectArray jRepresentation = (*env)->GetObjectArrayElement(env, jArray, i);
                if ((*env)->GetArrayLength(env, jRepresentation) == 2)
                {
                    jstring jUtf = (*env)->GetObjectArrayElement(env, jRepresentation, com_sun_glass_ui_mac_MacPasteboard_UtfIndex);
                    jobject jObject = (*env)->GetObjectArrayElement(env, jRepresentation, com_sun_glass_ui_mac_MacPasteboard_ObjectIndex);
                    
                    const jchar *chars = (*env)->GetStringChars(env, jUtf, NULL);
                    NSString *utf = [NSString stringWithCharacters:(UniChar *)chars length:(*env)->GetStringLength(env, jUtf)];
                    (*env)->ReleaseStringChars(env, jUtf, chars);
                    
                    SetNSPasteboardItemValueForUtf(env, item, jObject, utf);
                }
                else
                {
                    NSLog(@"Glass error: NSPasteboardItemFromArray found bad item with %d entries", (int)(*env)->GetArrayLength(env, jRepresentation));
                }
            }
        }
    }
    return item;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _initIDs
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1initIDs
(JNIEnv *env, jclass jPasteboard)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1initIDs");
    
//    NSLog(@"NSPasteboardTypeString: %@", NSPasteboardTypeString);
//    NSLog(@"NSPasteboardTypePDF: %@", NSPasteboardTypePDF);
//    NSLog(@"NSPasteboardTypeTIFF: %@", NSPasteboardTypeTIFF);
//    NSLog(@"NSPasteboardTypePNG: %@", NSPasteboardTypePNG);
//    NSLog(@"NSPasteboardTypeRTF: %@", NSPasteboardTypeRTF);
//    NSLog(@"NSPasteboardTypeRTFD: %@", NSPasteboardTypeRTFD);
//    NSLog(@"NSPasteboardTypeHTML: %@", NSPasteboardTypeHTML);
//    NSLog(@"NSPasteboardTypeTabularText: %@", NSPasteboardTypeTabularText);
//    NSLog(@"NSPasteboardTypeFont: %@", NSPasteboardTypeFont);
//    NSLog(@"NSPasteboardTypeColor: %@", NSPasteboardTypeColor);
//    NSLog(@"NSPasteboardTypeSound: %@", NSPasteboardTypeSound);
//    NSLog(@"NSPasteboardTypeMultipleTextSelection: %@", NSPasteboardTypeMultipleTextSelection);
//    NSLog(@"NSPasteboardTypeFindPanelSearchOptions: %@", NSPasteboardTypeFindPanelSearchOptions);
//    NSLog(@"kUTTypeURL: %@", (NSString*)kUTTypeURL);
//    NSLog(@"kUTTypeFileURL: %@", (NSString*)kUTTypeFileURL);
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _createSystemPasteboard
 * Signature: (I)J
 */
JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1createSystemPasteboard
(JNIEnv *env, jobject jPasteboard, jint jType)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1createSystemPasteboard: %d", jType);
    
    jlong ptr = 0L;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = nil;
        
        switch (jType)
        {
            case com_sun_glass_ui_mac_MacPasteboard_General:
                pasteboard = [NSPasteboard pasteboardWithName:NSGeneralPboard];
                break;
            case com_sun_glass_ui_mac_MacPasteboard_DragAndDrop:
                pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
                break;
        }
        
        ptr = ptr_to_jlong(pasteboard);
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return ptr;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _createUserPasteboard
 * Signature: (Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1createUserPasteboard
(JNIEnv *env, jobject jPasteboard, jstring jName)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1createUserPasteboard");
    
    jlong ptr = 0L;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        const jchar *chars = (*env)->GetStringChars(env, jName, NULL);
        NSString *name = [NSString stringWithCharacters:(UniChar *)chars length:(*env)->GetStringLength(env, jName)];
        (*env)->ReleaseStringChars(env, jName, chars);
        
        NSPasteboard *pasteboard = [[NSPasteboard pasteboardWithName:name] retain];
        ptr = ptr_to_jlong(pasteboard);
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return ptr;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getName
 * Signature: (J)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getName
(JNIEnv *env, jobject jPasteboard, jlong jPtr)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getName");
    
    jstring name = NULL;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        NSString *string = [pasteboard name];
        name = (*env)->NewStringUTF(env, [string UTF8String]);
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return name;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getUTFs
 * Signature: (J)[[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getUTFs
(JNIEnv *env, jobject jPasteboard, jlong jPtr)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getUTFs");
    
    jobjectArray utfs = NULL;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        //DumpPasteboard(pasteboard);
        
        NSArray *items = [pasteboard pasteboardItems];
        if ([items count] > 0)
        {
            utfs = (*env)->NewObjectArray(env, [items count], (*env)->FindClass(env, "java/lang/Object"), NULL);
            for (int i=0; i<[items count]; i++)
            {
                NSPasteboardItem *item = [items objectAtIndex:i];
                
                NSArray *types = [item types];
                if ([types count] > 0)
                {
                    jobjectArray array = (*env)->NewObjectArray(env, [types count], (*env)->FindClass(env, "java/lang/String"), NULL);
                    for (int j=0; j<[types count]; j++)
                    {
                        NSString *type = [types objectAtIndex:j];
                        //id property = [item stringForType:type];
                        //if (property != nil) // allow null as the platform itself does
                        {
                            (*env)->SetObjectArrayElement(env, array, j, (*env)->NewStringUTF(env, [type UTF8String]));
                        }
                    }
                    (*env)->SetObjectArrayElement(env, utfs, i, array);
                }
            }
        }
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return utfs;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getItemAsRawImage
 * Signature: (JI)[B
 */
JNIEXPORT jbyteArray JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getItemAsRawImage
(JNIEnv *env, jobject jPasteboard, jlong jPtr, jint jIndex)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getItemAsRawImage");
    
    jbyteArray bytes = NULL;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        NSArray *items = [pasteboard pasteboardItems];
        NSPasteboardItem *item = [items objectAtIndex:jIndex];
        
        // since this is a convenience method we'll try to do our best to return an image for this item
        // by trying all the following types if needed
        NSArray *utfs = [NSArray arrayWithObjects:
                         NSPasteboardTypeTIFF,
                         NSPasteboardTypePNG,
                         NSPasteboardTypePDF,
                         nil];
        
        NSData *data = nil;
        for (int i=0; i<[utfs count]; i++)
        {
            data = [item dataForType:[utfs objectAtIndex:i]];
            if (data != nil)
            {
                break;
            }
        }
        
        NSImage *image = [[[NSImage alloc] initWithData:data] autorelease];
        if (image == nil)
        {
            // if no image yet, try by referencing file url of this item (if it exists)
            NSString *file = [item stringForType:(NSString*)kUTTypeURL];
            if (file != nil)
            {
                NSURL *url = [NSURL URLWithString:file]; 
                image = [[[NSImage alloc] initByReferencingURL:url] autorelease];
            }
        }
        if (image == nil)
        {
            // if no image yet, try by referencing file url of this item (if it exists)
            NSString *file = [item stringForType:(NSString*)kUTTypeFileURL];
            if (file != nil)
            {
                NSURL *url = [NSURL URLWithString:file]; 
                image = [[[NSImage alloc] initByReferencingURL:url] autorelease];
            }
        }
        
#if 0
        // last try: if no image yet, try asking the pastebard for one (it's not per item though)
        if ((image == nil) && ([NSImage canInitWithPasteboard:pasteboard]))
        {
            image = [[[NSImage alloc] initWithPasteboard:pasteboard] autorelease];
        }
#endif
        
        if (image != nil)
        {
            CGImageRef cgImage = [image CGImageForProposedRect:NULL context:nil hints:nil];
            
            size_t width = CGImageGetWidth(cgImage);
            size_t height = CGImageGetHeight(cgImage);
            uint32_t *pixels = malloc(4*width*height);
            if (pixels != NULL)
            {
                CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
                CGContextRef ctx = CGBitmapContextCreate(pixels, width, height, 8, 4*width, space, kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Little);
                CGContextSetBlendMode(ctx, kCGBlendModeCopy);
                CGContextDrawImage(ctx, CGRectMake(0, 0, width, height), cgImage);
                CGContextFlush(ctx);
                
                bytes = ByteArrayFromPixels(env, pixels, width, height);
                
                CGColorSpaceRelease(space);
                free(pixels);
            }
        }
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return bytes;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getItemAsString
 * Signature: (JI)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getItemAsString
(JNIEnv *env, jobject jPasteboard, jlong jPtr, jint jIndex)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getItemAsString");
    
    jstring string = NULL;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        NSArray *items = [pasteboard pasteboardItems];
        NSPasteboardItem *item = [items objectAtIndex:jIndex];
        
        // since this is a convenience method we'll try to do our best to return a string for this item
        // by trying all the following types if needed
        NSArray *utfs = [NSArray arrayWithObjects:
                         NSPasteboardTypeString,
                         NSPasteboardTypeRTF,
                         NSPasteboardTypeMultipleTextSelection,
                         NSPasteboardTypeTabularText,
                         NSPasteboardTypeHTML,
                         NSPasteboardTypePDF,
                         NSPasteboardTypeRTFD,
                         nil];
        
        NSString *str = nil;
        for (int i=0; i<[utfs count]; i++)
        {
            str = [item stringForType:[utfs objectAtIndex:i]];
            if (str != nil)
            {
                string = (jobject)(*env)->NewStringUTF(env, [str UTF8String]);
                break;
            }
        }
        
        if (string == nil)
        {
            // if no string yet, try by referencing the item's url (if it exists)
            NSString *file = [item stringForType:(NSString*)kUTTypeURL];
            if (file != nil)
            {
                NSURL *url = [NSURL URLWithString:file]; 
                str = [NSString stringWithContentsOfURL:url encoding:NSUnicodeStringEncoding error:nil];
                if (str != nil)
                {
                    string = (jobject)(*env)->NewStringUTF(env, [str UTF8String]);
                }
            }
        }
        
        if (string == nil)
        {
            // if no string yet, try by referencing the item's url (if it exists)
            NSString *file = [item stringForType:(NSString*)kUTTypeFileURL];
            if (file != nil)
            {
                NSURL *url = [NSURL URLWithString:file]; 
                str = [NSString stringWithContentsOfURL:url encoding:NSUnicodeStringEncoding error:nil];
                if (str != nil)
                {
                    string = (jobject)(*env)->NewStringUTF(env, [str UTF8String]);
                }
            }
        }
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return string;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getItemStringForUTF
 * Signature: (JILjava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getItemStringForUTF
(JNIEnv *env, jobject jPasteboard, jlong jPtr, jint jIndex, jstring jUtf)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getItemStringForUTF");
    
    jstring string = NULL;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        const jchar *chars = (*env)->GetStringChars(env, jUtf, NULL);
        NSString *utf = [NSString stringWithCharacters:(UniChar *)chars length:(*env)->GetStringLength(env, jUtf)];
        (*env)->ReleaseStringChars(env, jUtf, chars);
        
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        NSArray *items = [pasteboard pasteboardItems];
        NSPasteboardItem *item = [items objectAtIndex:jIndex];
        
        NSString *str = [item stringForType:utf];
        if (str != nil)
        {
            string = (jobject)(*env)->NewStringUTF(env, [str UTF8String]);
        }
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return string;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getItemBytesForUTF
 * Signature: (JILjava/lang/String;)[B
 */
JNIEXPORT jbyteArray JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getItemBytesForUTF
(JNIEnv *env, jobject jPasteboard, jlong jPtr, jint jIndex, jstring jUtf)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getItemBytesForUTF");
    
    jbyteArray bytes = NULL;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        const jchar *chars = (*env)->GetStringChars(env, jUtf, NULL);
        NSString *utf = [NSString stringWithCharacters:(UniChar *)chars length:(*env)->GetStringLength(env, jUtf)];
        (*env)->ReleaseStringChars(env, jUtf, chars);
        
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        NSArray *items = [pasteboard pasteboardItems];
        NSPasteboardItem *item = [items objectAtIndex:jIndex];
        
        NSData *data = [item dataForType:utf];
        bytes = ByteArrayFromNSData(env, data);
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return bytes;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getItemForUTF
 * Signature: (JILjava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getItemForUTF
(JNIEnv *env, jobject jPasteboard, jlong jPtr, jint jIndex, jstring jUtf)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getItemForUTF");
    
    jlong ptr = 0L;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        const jchar *chars = (*env)->GetStringChars(env, jUtf, NULL);
        NSString *utf = [NSString stringWithCharacters:(UniChar *)chars length:(*env)->GetStringLength(env, jUtf)];
        (*env)->ReleaseStringChars(env, jUtf, chars);
        
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        NSArray *items = [pasteboard pasteboardItems];
        NSPasteboardItem *item = [items objectAtIndex:jIndex];
        
        id property = [[item propertyListForType:utf] retain]; // notice we retain
        ptr = ptr_to_jlong(property);
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return ptr;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _putItemsFromArray
 * Signature: (J[Ljava/lang/Object;I)J
 */
JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1putItemsFromArray
(JNIEnv *env, jobject jPasteboard, jlong jPtr, jobjectArray jObjects, jint supportedActions)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1putItemsFromArray");
    
    jlong seed = 0L;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        seed = [pasteboard clearContents];
        
        jsize itemCount = (*env)->GetArrayLength(env, jObjects);
        //NSLog(@"Java_com_sun_glass_ui_mac_MacPasteboard__1putItems itemCount: %d", itemCount);
        if (itemCount > 0)
        {
            NSMutableArray *objects = [NSMutableArray arrayWithCapacity:itemCount];
            for (int i=0; i<itemCount; i++)
            {
                jobject array = (*env)->GetObjectArrayElement(env, jObjects, i);
                if (array != NULL)
                {
                    NSPasteboardItem *item = NSPasteboardItemFromArray(env, array);
                    [objects addObject:item];
                }
            }
            // http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/PasteboardGuide106/Articles/pbCustom.html
            [pasteboard writeObjects:objects];
            
            if (pasteboard == [NSPasteboard pasteboardWithName:NSDragPboard])
            {
                [GlassDragSource flushWithMask:supportedActions];
            }
        }
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return seed;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _clear
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1clear
(JNIEnv *env, jobject jPasteboard, jlong jPtr)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1clear");
    
    jlong seed = 0L;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        seed = [pasteboard clearContents];
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return seed;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getSeed
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getSeed
(JNIEnv *env, jobject jPasteboard, jlong jPtr)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getSeed");
    
    jlong seed = 0L;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        seed = [pasteboard changeCount];
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return seed;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _release
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1release
(JNIEnv *env, jobject jPasteboard, jlong jPtr)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1release");
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        [pasteboard releaseGlobally];
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
}

/*
 * Class:     com_sun_glass_ui_mac_MacPasteboard
 * Method:    _getAllowedOperation
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacPasteboard__1getAllowedOperation
(JNIEnv *env, jobject jPasteboard, jlong jPtr)
{
    LOG("Java_com_sun_glass_ui_mac_MacPasteboard__1getAllowedOperation");
    
    jint mask = 0;
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    GLASS_POOL_ENTER;
    {
        NSPasteboard *pasteboard = (NSPasteboard*)jlong_to_ptr(jPtr);
        if (pasteboard == [NSPasteboard pasteboardWithName:NSDragPboard])
        {
            // retrieve the mask for DnD
            mask = [GlassDragSource getMask];
        }
        else
        {
            // we can always copy from a NSPasteboard
            mask = com_sun_glass_ui_Clipboard_ACTION_COPY;
        }
    }
    GLASS_POOL_EXIT;
    GLASS_CHECK_EXCEPTION(env);
    
    return mask;
}
