/*
 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

//#define DND_DEBUG TRUE

#import "java_awt_dnd_DnDConstants.h"

#import <Cocoa/Cocoa.h>
#import <JavaNativeFoundation/JavaNativeFoundation.h>

#import "AWTEvent.h"
#import "AWTView.h"
#import "CDataTransferer.h"
#import "CDropTarget.h"
#import "CDragSource.h"
#import "DnDUtilities.h"
#import "ThreadUtilities.h"


// When sIsJavaDragging is true Java drag gesture has been recognized and a drag is/has been initialized.
// We must stop posting MouseEvent.MOUSE_DRAGGED events for the duration of the drag or all hell will break
// loose in shared code - tracking state going haywire.
static BOOL sIsJavaDragging;


@interface NSEvent(AWTAdditions)

+ (void)javaDraggingBegin;
+ (void)javaDraggingEnd;

@end


@implementation NSEvent(AWTAdditions)


+ (void)javaDraggingBegin
{
    sIsJavaDragging = YES;
}

+ (void)javaDraggingEnd
{
    // sIsJavaDragging is reset on mouseDown as well.
    sIsJavaDragging = NO;
}
@end

JNF_CLASS_CACHE(DataTransfererClass, "sun/awt/datatransfer/DataTransferer");
JNF_CLASS_CACHE(CDragSourceContextPeerClass, "sun/lwawt/macosx/CDragSourceContextPeer");
JNF_CLASS_CACHE(CImageClass, "sun/lwawt/macosx/CImage");

static NSDragOperation    sDragOperation;
static NSPoint            sDraggingLocation;

static BOOL                sNeedsEnter;

@interface CDragSource ()
// Updates from the destination to the source
- (void) postDragEnter;
- (void) postDragExit;
// Utility
- (NSPoint) mapNSScreenPointToJavaWithOffset:(NSPoint) point;
@end

@implementation CDragSource

- (id)        init:(jobject)jDragSourceContextPeer
         component:(jobject)jComponent
           control:(id)control
      transferable:(jobject)jTransferable
      triggerEvent:(jobject)jTrigger
          dragPosX:(jint)dragPosX
          dragPosY:(jint)dragPosY
         modifiers:(jint)extModifiers
        clickCount:(jint)clickCount
         timeStamp:(jlong)timeStamp
         dragImage:(jobject)jDragImage
  dragImageOffsetX:(jint)jDragImageOffsetX
  dragImageOffsetY:(jint)jDragImageOffsetY
     sourceActions:(jint)jSourceActions
           formats:(jlongArray)jFormats
         formatMap:(jobject)jFormatMap
{
    self = [super init];
    DLog2(@"[CDragSource init]: %@\n", self);

    fView = nil;
    fComponent = nil;

    // Construct the object if we have a valid model for it:
    if (control != nil) {
        JNIEnv *env = [ThreadUtilities getJNIEnv];
        fComponent = JNFNewGlobalRef(env, jComponent);
        fDragSourceContextPeer = JNFNewGlobalRef(env, jDragSourceContextPeer);

        fTransferable = JNFNewGlobalRef(env, jTransferable);
        fTriggerEvent = JNFNewGlobalRef(env, jTrigger);

        if (jDragImage) {
            JNF_MEMBER_CACHE(nsImagePtr, CImageClass, "ptr", "J");
            jlong imgPtr = JNFGetLongField(env, jDragImage, nsImagePtr);
            fDragImage = (NSImage*) jlong_to_ptr(imgPtr); // Double-casting prevents compiler 'd$|//

            [fDragImage retain];
        }

        fDragImageOffset = NSMakePoint(jDragImageOffsetX, jDragImageOffsetY);

        fSourceActions = jSourceActions;
        fFormats = JNFNewGlobalRef(env, jFormats);
        fFormatMap = JNFNewGlobalRef(env, jFormatMap);

        fTriggerEventTimeStamp = timeStamp;
        fDragPos = NSMakePoint(dragPosX, dragPosY);
        fClickCount = clickCount;
        fModifiers = extModifiers;

        // Set this object as a dragging source:

        fView = [(AWTView *) control retain];
        [fView setDragSource:self];

        // Let AWTEvent know Java drag is getting underway:
        [NSEvent javaDraggingBegin];
    }

    else {
        [self release];
        self = nil;
    }

    return self;
}

- (void)removeFromView:(JNIEnv *)env
{
    DLog2(@"[CDragSource removeFromView]: %@\n", self);

    // Remove this dragging source from the view:
    [((AWTView *) fView) setDragSource:nil];

    // Clean up JNI refs
    if (fComponent != NULL) {
        JNFDeleteGlobalRef(env, fComponent);
        fComponent = NULL;
    }

    if (fDragSourceContextPeer != NULL) {
        JNFDeleteGlobalRef(env, fDragSourceContextPeer);
        fDragSourceContextPeer = NULL;
    }

    if (fTransferable != NULL) {
        JNFDeleteGlobalRef(env, fTransferable);
        fTransferable = NULL;
    }

    if (fTriggerEvent != NULL) {
        JNFDeleteGlobalRef(env, fTriggerEvent);
        fTriggerEvent = NULL;
    }

    if (fFormats != NULL) {
        JNFDeleteGlobalRef(env, fFormats);
        fFormats = NULL;
    }

    if (fFormatMap != NULL) {
        JNFDeleteGlobalRef(env, fFormatMap);
        fFormatMap = NULL;
    }

    CFRelease(self); // GC
}

- (void)dealloc
{
    DLog2(@"[CDragSource dealloc]: %@\n", self);

    // Delete or release local data:
    [fView release];
    fView = nil;

    [fDragImage release];
    fDragImage = nil;

    [super dealloc];
}
//- (void)finalize { [super finalize]; }


// Appropriated from Windows' awt_DataTransferer.cpp:
//
// * NOTE: This returns a JNI Local Ref. Any code that calls must call DeleteLocalRef with the return value.
//
- (jobject)dataTransferer:(JNIEnv*)env
{
    JNF_STATIC_MEMBER_CACHE(getInstanceMethod, DataTransfererClass, "getInstance", "()Lsun/awt/datatransfer/DataTransferer;");
    return JNFCallStaticObjectMethod(env, getInstanceMethod);
}

// Appropriated from Windows' awt_DataTransferer.cpp:
//
// * NOTE: This returns a JNI Local Ref. Any code that calls must call DeleteLocalRef with the return value.
//
- (jbyteArray)convertData:(jlong)format
{
    JNIEnv*    env = [ThreadUtilities getJNIEnv];
    jobject    transferer = [self dataTransferer:env];
    jbyteArray data = nil;

    if (transferer != NULL) {
        JNF_MEMBER_CACHE(convertDataMethod, DataTransfererClass, "convertData", "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B");
        data = JNFCallObjectMethod(env, transferer, convertDataMethod, fComponent, fTransferable, format, fFormatMap, (jboolean) TRUE);
    }

    return data;
}


// Encodes a byte array of zero-terminated filenames into an NSArray of NSStrings representing them.
// Borrowed and adapted from awt_DataTransferer.c, convertFileType().
- (id)getFileList:(jbyte *)jbytes dataLength:(jsize)jbytesLength
{
    jsize  strings = 0;
    jsize  i;

    // Get number of filenames while making sure to skip over empty strings.
    for (i = 1; i < jbytesLength; i++) {
        if (jbytes[i] == '\0' && jbytes[i - 1] != '\0')
            strings++;
    }

    // Create the file list to return:
    NSMutableArray* fileList = [NSMutableArray arrayWithCapacity:strings];

    for (i = 0; i < jbytesLength; i++) {
        char* start = (char *) &jbytes[i];

        // Skip over empty strings:
        if (start[0] == '\0') {
            continue;
        }

        // Update the position marker:
        i += strlen(start);

        // Add this filename to the file list:
        NSMutableString* fileName = [NSMutableString stringWithUTF8String:start];
        // Decompose the filename
        CFStringNormalize((CFMutableStringRef)fileName, kCFStringNormalizationFormD);
        [fileList addObject:fileName];
    }

    // 03-01-09 Note: keep this around for debugging.
    // return [NSArray arrayWithObjects:@"/tmp/foo1", @"/tmp/foo2", nil];

    return ([fileList count] > 0 ? fileList : nil);
}


// Set up the pasteboard for dragging:
- (BOOL)declareTypesToPasteboard:(NSPasteboard *)pb withEnv:(JNIEnv *) env {
    // 9-20-02 Note: leave this here for debugging:
    //[pb declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: self];
    //return TRUE;

    // Get byte array elements:
    jboolean isCopy;
    jlong* jformats = (*env)->GetLongArrayElements(env, fFormats, &isCopy);
    if (jformats == nil)
        return FALSE;

    // Allocate storage arrays for dragging types to register with the pasteboard:
    jsize formatsLength = (*env)->GetArrayLength(env, fFormats);
    NSMutableArray* pbTypes = [[NSMutableArray alloc] initWithCapacity:formatsLength];

    // And assume there are no NS-type data: [Radar 3065621]
    // This is to be able to drop transferables containing only a serialized object flavor, e.g.:
    //   "JAVA_DATAFLAVOR:application/x-java-serialized-object; class=java.awt.Label".
    BOOL hasNSTypeData = false;

    // Collect all supported types in a pasteboard format into the storage arrays:
    jsize i;
    for (i = 0; i < formatsLength; i++) {
        jlong jformat = jformats[i];

        if (jformat >= 0) {
            NSString* type = formatForIndex(jformat);

            // Add element type to the storage array.
            if (type != nil) {
                if ([type hasPrefix:@"JAVA_DATAFLAVOR:application/x-java-jvm-local-objectref;"] == false) {
                    [pbTypes addObject:type];

                    // This is a good approximation if not perfect. A conclusive search would
                    // have to be done matching all defined strings in AppKit's commonStrings.h.
                    hasNSTypeData = [type hasPrefix:@"NS"] || [type hasPrefix:@"NeXT"] || [type hasPrefix:@"public."];
                }
            }
        }
    }

    // 1-16-03 Note: [Radar 3065621]
    // When TransferHandler is used with Swing components it puts only a type like this on the pasteboard:
    //   "JAVA_DATAFLAVOR:application/x-java-jvm-local-objectref; class=java.lang.String"
    // And there's similar type for serialized object only transferables.
    // Since our drop targets aren't trained for arbitrary data types yet we need to fake an empty string
    // which will cause drop target handlers to fire.
    // KCH  - 3550405 If the drag is between Swing components, formatsLength == 0, so expand the check.
    // Also, use a custom format rather than NSString, since that will prevent random views from accepting the drag
    if (hasNSTypeData == false && formatsLength >= 0) {
        [pbTypes addObject:[DnDUtilities javaPboardType]];
    }

    (*env)->ReleaseLongArrayElements(env, fFormats, jformats, JNI_ABORT);

    // Declare pasteboard types. If the types array is empty we still want to declare them
    // as otherwise an old set of types/data would remain on the pasteboard.
    NSUInteger typesCount = [pbTypes count];
    [pb declareTypes:pbTypes owner: self];

    // KCH - Lame conversion bug between Cocoa and Carbon drag types
    // If I provide the filenames _right now_, NSFilenamesPboardType is properly converted to CoreDrag flavors
    // If I try to wait until pasteboard:provideDataForType:, the conversion won't happen
    // and pasteboard:provideDataForType: won't even get called! (unless I go over a Cocoa app)
    if ([pbTypes containsObject:NSFilenamesPboardType]) {
        [self pasteboard:pb provideDataForType:NSFilenamesPboardType];
    }

    [pbTypes release];

    return typesCount > 0 ? TRUE : FALSE;
}

// This is an NSPasteboard callback. In declareTypesToPasteboard:withEnv:, we only declared the types
// When the AppKit DnD system actually needs the data, this method will be invoked.
// Note that if the transfer is handled entirely from Swing (as in a local-vm drag), this method may never be called.
- (void)pasteboard:(NSPasteboard *)pb provideDataForType:(NSString *)type {
    AWT_ASSERT_APPKIT_THREAD;

    // 9-20-02 Note: leave this here for debugging:
    //[pb setString: @"Hello, World!" forType: NSStringPboardType];
    // return;

    // Set up Java environment:
    JNIEnv* env = [ThreadUtilities getJNIEnv];

    id pbData = nil;

    // Collect data in a pasteboard format:
    jlong jformat = indexForFormat(type);
    if (jformat >= 0) {
        // Convert DataTransfer data to a Java byte array:
        // Note that this will eventually call getTransferData()
        jbyteArray jdata = [self convertData:jformat];

        if (jdata != nil) {
            jboolean isCopy;
            jsize jdataLength = (*env)->GetArrayLength(env, jdata);
            jbyte* jbytedata = (*env)->GetByteArrayElements(env, jdata, &isCopy);

            if (jdataLength > 0 && jbytedata != nil) {
                // Get element data to the storage array. For NSFilenamesPboardType type we use
                // an NSArray-type data - NSData-type data would cause a crash.
                if (type != nil) {
                    pbData = ([type isEqualTo:NSFilenamesPboardType]) ?
                        [self getFileList:jbytedata dataLength:jdataLength] :
                        [NSData dataWithBytes:jbytedata length:jdataLength];
                }
            }

            (*env)->ReleaseByteArrayElements(env, jdata, jbytedata, JNI_ABORT);

            (*env)->DeleteLocalRef(env, jdata);
        }
    }

    // If we are the custom type that matches local-vm drags, set an empty NSData
    if ( (pbData == nil) && ([type isEqualTo:[DnDUtilities javaPboardType]]) ) {
        pbData = [NSData dataWithBytes:"" length:1];
    }

    // Add pasteboard data for the type:
    // Remember, NSFilenamesPboardType's data is NSArray (property list), not NSData!
    // We must use proper pb accessor depending on the data type.
    if ([pbData isKindOfClass:[NSArray class]])
        [pb setPropertyList:pbData forType:type];
    else
        [pb setData:pbData forType:type];
}


- (void)validateDragImage
{
    // Make a small blank image if we don't have a drag image:
    if (fDragImage == nil) {
        // 9-30-02 Note: keep this around for debugging:
        fDragImage = [[NSImage alloc] initWithSize:NSMakeSize(21, 21)];
        NSSize imageSize = [fDragImage size];

        NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
            pixelsWide:imageSize.width pixelsHigh:imageSize.height bitsPerSample:8 samplesPerPixel:4
            hasAlpha:YES isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace bytesPerRow:0 bitsPerPixel:32];

        [fDragImage addRepresentation:imageRep];
        fDragImageOffset = NSMakePoint(0, 0);

        [imageRep release];
    }
}

- (NSEvent*)nsDragEvent:(BOOL)isDrag
{
    // Get NSView for the drag source:
    NSWindow* window = [fView window];

    NSInteger windowNumber = [window windowNumber];
    NSGraphicsContext* graphicsContext = [NSGraphicsContext graphicsContextWithWindow:window];

    // Convert mouse coordinates to NS:
    NSPoint eventLocation = [fView convertPoint:NSMakePoint(fDragPos.x, fDragPos.y) toView:nil];
    eventLocation.y = [[fView window] frame].size.height - eventLocation.y;
    
    // Convert fTriggerEventTimeStamp to NS - AWTEvent.h defines UTC(nsEvent) as ((jlong)[event timestamp] * 1000):
    NSTimeInterval timeStamp = fTriggerEventTimeStamp / 1000;

    // Convert fModifiers (extModifiers) to NS:
    NSEventType mouseButtons = 0;
    float pressure = 0.0;
    if (isDrag) {
        mouseButtons = (NSEventType) [DnDUtilities mapJavaExtModifiersToNSMouseDownButtons:fModifiers];
        pressure = 1.0;
    } else {
        mouseButtons = (NSEventType) [DnDUtilities mapJavaExtModifiersToNSMouseUpButtons:fModifiers];
    }

    // Convert fModifiers (extModifiers) to NS:
    NSUInteger modifiers = JavaModifiersToNsKeyModifiers(fModifiers, TRUE); 

    // Just a dummy value ...
    NSInteger eventNumber = 0;

    // Make a native autoreleased dragging event:
    NSEvent* dragEvent = [NSEvent mouseEventWithType:mouseButtons location:eventLocation
        modifierFlags:modifiers timestamp:timeStamp windowNumber:windowNumber context:graphicsContext
        eventNumber:eventNumber clickCount:fClickCount pressure:pressure];

    return dragEvent;
}

- (void)doDrag
{
    AWT_ASSERT_APPKIT_THREAD;

    DLog2(@"[CDragSource doDrag]: %@\n", self);

    // Set up Java environment:
    JNIEnv *env = [ThreadUtilities getJNIEnv];

    // Set up the pasteboard:
    NSPasteboard *pb = [NSPasteboard pasteboardWithName: NSDragPboard];
    [self declareTypesToPasteboard:pb withEnv:env];

    // Make a native autoreleased NS dragging event:
    NSEvent *dragEvent = [self nsDragEvent:YES];

    // Get NSView for the drag source:
    NSView *view = fView;

    // Make sure we have a valid drag image:
    [self validateDragImage];
    NSImage* dragImage = fDragImage;

    // Get drag origin and offset:
    NSPoint dragOrigin = [dragEvent locationInWindow];
    dragOrigin.x += fDragImageOffset.x;
    dragOrigin.y -= fDragImageOffset.y + [dragImage size].height;

    // Drag offset values don't seem to matter:
    NSSize dragOffset = NSMakeSize(0, 0);

    // These variables should be set based on the transferable:
    BOOL isFileDrag = FALSE;
    BOOL fileDragPromises = FALSE;

    DLog(@"[CDragSource drag]: calling dragImage/File:");
    DLog3(@"  - drag origin: %f, %f", fDragPos.x, fDragPos.y);
    DLog5(@"  - drag image: %f, %f (%f x %f)", fDragImageOffset.x, fDragImageOffset.y, [dragImage size].width, [dragImage size].height);
    DLog3(@"  - event point (window) %f, %f", [dragEvent locationInWindow].x, [dragEvent locationInWindow].y);
    DLog3(@"  - drag point (view) %f, %f", dragOrigin.x, dragOrigin.y);
    // Set up the fDragKeyModifier, so we know if the operation has changed
    // Set up the fDragMouseModifier, so we can |= it later (since CoreDrag doesn't tell us mouse states during a drag)
    fDragKeyModifiers = [DnDUtilities extractJavaExtKeyModifiersFromJavaExtModifiers:fModifiers];
    fDragMouseModifiers = [DnDUtilities extractJavaExtMouseModifiersFromJavaExtModifiers:fModifiers];

    sNeedsEnter = YES;

    @try {
        // Data dragging:
        if (isFileDrag == FALSE) {
            [view dragImage:dragImage at:dragOrigin offset:dragOffset event:dragEvent pasteboard:pb source:view slideBack:YES];
        } else if (fileDragPromises == FALSE) {
            // File dragging:
            NSLog(@"[CDragSource drag]: file dragging is unsupported.");
            NSString* fileName = nil;                                // This should be set based on the transferable.
            NSRect    fileLocationRect = NSMakeRect(0, 0, 0, 0);    // This should be set based on the filename.

            BOOL success = [view dragFile:fileName fromRect:fileLocationRect slideBack:YES event:dragEvent];
            if (success == TRUE) {                                    // One would erase dragged file if this was a move operation.
            }
        } else {
            // Promised file dragging:
            NSLog(@"[CDragSource drag]: file dragging promises are unsupported.");
            NSArray* fileTypesArray = nil;                            // This should be set based on the transferable.
            NSRect   fileLocationRect = NSMakeRect(0, 0, 0, 0);        // This should be set based on all filenames.

            BOOL success = [view dragPromisedFilesOfTypes:fileTypesArray fromRect:fileLocationRect source:view slideBack:YES event:dragEvent];
            if (success == TRUE) {                                    // One would write out the promised files here.
            }
        }

        NSPoint point = [self mapNSScreenPointToJavaWithOffset:sDraggingLocation];

        // Convert drag operation to Java:
        jint dragOp = [DnDUtilities mapNSDragOperationToJava:sDragOperation];

        // Drag success must acount for DragOperationNone:
        jboolean success = (dragOp != java_awt_dnd_DnDConstants_ACTION_NONE);

        // We have a problem here... we don't send DragSource dragEnter/Exit messages outside of our own process
        // because we don't get anything from AppKit/CoreDrag
        // This means that if you drag outside of the app and drop, even if it's valid, a dragDropFinished is posted without dragEnter
        // I'm worried that this might confuse Java, so we're going to send a "bogus" dragEnter if necessary (only if the drag succeeded)
        if (success && sNeedsEnter) {
            [self postDragEnter];
        }

        // DragSourceContextPeer.dragDropFinished() should be called even if there was an error:
        JNF_MEMBER_CACHE(dragDropFinishedMethod, CDragSourceContextPeerClass, "dragDropFinished", "(ZIII)V");
        DLog3(@"  -> posting dragDropFinished, point %f, %f", point.x, point.y);
        JNFCallVoidMethod(env, fDragSourceContextPeer, dragDropFinishedMethod, success, dragOp, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
                JNF_MEMBER_CACHE(resetHoveringMethod, CDragSourceContextPeerClass, "resetHovering", "()V");
        JNFCallVoidMethod(env, fDragSourceContextPeer, resetHoveringMethod); // Hust reset static variable
    } @finally {
        sNeedsEnter = NO;
    }

    // We have to do this, otherwise AppKit doesn't know we're finished dragging. Yup, it's that bad.
    if ([[[NSRunLoop currentRunLoop] currentMode] isEqualTo:NSEventTrackingRunLoopMode]) {
        [NSApp postEvent:[self nsDragEvent:NO] atStart:YES];
    }

    DLog2(@"[CDragSource doDrag] end: %@\n", self);
}

- (void)drag
{
    AWT_ASSERT_NOT_APPKIT_THREAD;

    [self performSelectorOnMainThread:@selector(doDrag) withObject:nil waitUntilDone:YES]; // AWT_THREADING Safe (called from unique asynchronous thread)
}

/********************************  BEGIN NSDraggingSource Interface  ********************************/

- (void)draggingOperationChanged:(NSDragOperation)dragOp {
    //DLog2(@"[CDragSource draggingOperationChanged]: %@\n", self);

    JNIEnv* env = [ThreadUtilities getJNIEnv];

    jint targetActions = fSourceActions;
    if ([CDropTarget currentDropTarget]) targetActions = [[CDropTarget currentDropTarget] currentJavaActions];

    NSPoint point = [self mapNSScreenPointToJavaWithOffset:sDraggingLocation];
    DLog3(@"  -> posting operationChanged, point %f, %f", point.x, point.y);
    jint modifiedModifiers = fDragKeyModifiers | fDragMouseModifiers | [DnDUtilities javaKeyModifiersForNSDragOperation:dragOp];

    JNF_MEMBER_CACHE(operationChangedMethod, CDragSourceContextPeerClass, "operationChanged", "(IIII)V");
    JNFCallVoidMethod(env, fDragSourceContextPeer, operationChangedMethod, targetActions, modifiedModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
}

- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)localDrag {
    //DLog2(@"[CDragSource draggingSourceOperationMaskForLocal]: %@\n", self);
    return [DnDUtilities mapJavaDragOperationToNS:fSourceActions];
}

/* 9-16-02 Note: we don't support promises yet.
- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination {
}*/

- (void)draggedImage:(NSImage *)image beganAt:(NSPoint)screenPoint {
    DLog4(@"[CDragSource draggedImage beganAt]: (%f, %f) %@\n", screenPoint.x, screenPoint.y, self);

    // Initialize static variables:
    sDragOperation = NSDragOperationNone;
    sDraggingLocation = screenPoint;
}

- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation {
    DLog4(@"[CDragSource draggedImage endedAt:]: (%f, %f) %@\n", screenPoint.x, screenPoint.y, self);

    sDraggingLocation = screenPoint;
    sDragOperation = operation;
}

- (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint {
    //DLog4(@"[CDragSource draggedImage moved]: (%d, %d) %@\n", (int) screenPoint.x, (int) screenPoint.y, self);
    JNIEnv* env = [ThreadUtilities getJNIEnv];

JNF_COCOA_ENTER(env);
    // There are two things we would be interested in:
    // a) mouse pointer has moved
    // b) drag actions (key modifiers) have changed

    BOOL notifyJava = FALSE;

    // a) mouse pointer has moved:
    if (NSEqualPoints(screenPoint, sDraggingLocation) == FALSE) {
        //DLog2(@"[CDragSource draggedImage:movedTo]: mouse moved, %@\n", self);
        notifyJava = TRUE;
    }

    // b) drag actions (key modifiers) have changed:
    jint modifiers = NsKeyModifiersToJavaModifiers([NSEvent modifierFlags], YES);
    if (fDragKeyModifiers != modifiers) {
        NSDragOperation currentOp = [DnDUtilities nsDragOperationForModifiers:[NSEvent modifierFlags]];
        NSDragOperation allowedOp = [DnDUtilities mapJavaDragOperationToNS:fSourceActions] & currentOp;

        fDragKeyModifiers = modifiers;

        if (sDragOperation != allowedOp) {
            sDragOperation = allowedOp;
            [self draggingOperationChanged:allowedOp];
        }
    }

    // Should we notify Java things have changed?
    if (notifyJava) {
        sDraggingLocation = screenPoint;

        NSPoint point = [self mapNSScreenPointToJavaWithOffset:screenPoint];

        jint targetActions = fSourceActions;
        if ([CDropTarget currentDropTarget]) targetActions = [[CDropTarget currentDropTarget] currentJavaActions];

        // Motion: dragMotion, dragMouseMoved
        DLog4(@"[CDragSource draggedImage moved]: (%f, %f) %@\n", screenPoint.x, screenPoint.y, self);

        DLog3(@"  -> posting dragMotion, point %f, %f", point.x, point.y);
        JNF_MEMBER_CACHE(dragMotionMethod, CDragSourceContextPeerClass, "dragMotion", "(IIII)V");
        JNFCallVoidMethod(env, fDragSourceContextPeer, dragMotionMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)

        DLog3(@"  -> posting dragMouseMoved, point %f, %f", point.x, point.y);
        JNF_MEMBER_CACHE(dragMouseMovedMethod, CDragSourceContextPeerClass, "dragMouseMoved", "(IIII)V");
        JNFCallVoidMethod(env, fDragSourceContextPeer, dragMouseMovedMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
    }
JNF_COCOA_EXIT(env);
}

- (BOOL)ignoreModifierKeysWhileDragging {
    //DLog2(@"[CDragSource ignoreModifierKeysWhileDragging]: %@\n", self);
    return NO;
}

/********************************  END NSDraggingSource Interface  ********************************/


// postDragEnter and postDragExit are called from CDropTarget when possible and appropriate
// Currently only possible if source and target are in the same process
- (void) postDragEnter {
    JNIEnv *env = [ThreadUtilities getJNIEnv];
    sNeedsEnter = NO;

    jint targetActions = fSourceActions;
    if ([CDropTarget currentDropTarget]) targetActions = [[CDropTarget currentDropTarget] currentJavaActions];

    NSPoint point = [self mapNSScreenPointToJavaWithOffset:sDraggingLocation];
    DLog3(@"  -> posting dragEnter, point %f, %f", point.x, point.y);
    JNF_MEMBER_CACHE(dragEnterMethod, CDragSourceContextPeerClass, "dragEnter", "(IIII)V");
    JNFCallVoidMethod(env, fDragSourceContextPeer, dragEnterMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
}

- (void) postDragExit {
    JNIEnv *env = [ThreadUtilities getJNIEnv];
    sNeedsEnter = YES;

    NSPoint point = [self mapNSScreenPointToJavaWithOffset:sDraggingLocation];
    DLog3(@"  -> posting dragExit, point %f, %f", point.x, point.y);
    JNF_MEMBER_CACHE(dragExitMethod, CDragSourceContextPeerClass, "dragExit", "(II)V");
    JNFCallVoidMethod(env, fDragSourceContextPeer, dragExitMethod, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
}


// Java assumes that the origin is the top-left corner of the screen.
// Cocoa assumes that the origin is the bottom-left corner of the screen.
// Adjust the y coordinate to account for this.
// NOTE: Also need to take into account the 0 screen relative screen coords.
//  This is because all screen coords in Cocoa are relative to the 0 screen.
// Also see +[CWindow convertAWTToCocoaScreenRect]
// NSScreen-to-JavaScreen mapping:
- (NSPoint) mapNSScreenPointToJavaWithOffset:(NSPoint)screenPoint {
    NSRect mainR = [[[NSScreen screens] objectAtIndex:0] frame];
    NSPoint point = NSMakePoint(screenPoint.x, mainR.size.height - (screenPoint.y));

    // Adjust the point with the drag image offset to get the real mouse hotspot:
    // The point should remain in screen coordinates (as per DragSourceEvent.getLocation() documentation)
    point.x -= fDragImageOffset.x;
    point.y -= ([fDragImage size].height + fDragImageOffset.y);

    return point;
}

@end
