#ifndef __IUPCOCOA_DRAGDROP_H
#define __IUPCOCOA_DRAGDROP_H

#import <Cocoa/Cocoa.h>

#include "iup.h"


extern const void* IUPSOURCEDRAG_ASSOCIATED_OBJ_KEY;
extern const void* IUPTARGETDROP_ASSOCIATED_OBJ_KEY;

@interface IupTargetDropAssociatedData : NSObject
@property(nonatomic, assign) Ihandle* ihandle;
@property(nonatomic, copy) NSArray<NSString*>* dropRegisteredTypes;
@property(nonatomic, assign, getter=isDropTargetEnabled) bool dropTargetEnabled;

/* These must be weak references because we don't want to create a retain cycle back to the view we are operating on. */
@property(nonatomic, assign) NSView* mainView;
@property(nonatomic, assign) NSView* rootView;

@end

#ifdef GNUSTEP
@interface IupSourceDragAssociatedData : NSObject <NSDraggingSource, NSPasteboardItemDataProvider>
#else
@interface IupSourceDragAssociatedData : NSObject <NSDraggingSource, NSPasteboardTypeOwner, NSPasteboardItemDataProvider, NSFilePromiseProviderDelegate>
#endif
@property(nonatomic, assign) Ihandle* ihandle;
/* Used to distinguish between needing copy or if drag is actually enabled. Setting the types assumes copy is active. */
@property(nonatomic, assign, getter=isDragSourceEnabled) bool dragSourceEnabled;
@property(nonatomic, copy) NSArray<NSString*>* dragRegisteredTypes;
@property(nonatomic, copy) NSString* defaultFilePromiseName; /* Used for when the user doesn't define a callback. */
- (bool) usesFilePromise;

/* These must be weak references because we don't want to create a retain cycle back to the view we are operating on. */
@property(nonatomic, assign) NSView* mainView;
@property(nonatomic, assign) NSView* rootView;

/* @protocol: NSPasteboardItemDataProvider */
- (void) pasteboard:(NSPasteboard*)paste_board item:(NSPasteboardItem*)pasteboard_item provideDataForType:(NSPasteboardType)type_name;

/* @protocol: NSDraggingSource */
- (NSDragOperation) draggingSession:(NSDraggingSession*)dragging_session sourceOperationMaskForDraggingContext:(NSDraggingContext)dragging_context;


#ifndef GNUSTEP
- (NSDraggingItem*) defaultDraggingItem;
#endif
- (NSPasteboardItem*) defaultPasteboardItem;


#ifndef GNUSTEP
/* @protocol: NSFilePromiseProviderDelegate */
- (NSString*) filePromiseProvider:(NSFilePromiseProvider*)file_promise_provider fileNameForType:(NSString*)file_type;
/* @protocol: NSFilePromiseProviderDelegate */
- (void) filePromiseProvider:(NSFilePromiseProvider*)file_promise_provider writePromiseToURL:(NSURL*)write_url completionHandler:(void (^)(NSError* errorOrNil))completion_handler;
#endif

- (void) draggingSession:(NSDraggingSession*)dragging_session willBeginAtPoint:(NSPoint)screen_point;
- (void) draggingSession:(NSDraggingSession*)dragging_session endedAtPoint:(NSPoint)screen_point operation:(NSDragOperation)drag_operation;

@end


IupTargetDropAssociatedData* cocoaTargetDropGetAssociatedData(Ihandle* ih);
IupSourceDragAssociatedData* cocoaSourceDragGetAssociatedData(Ihandle* ih);

IupTargetDropAssociatedData* cocoaTargetDropCreateAssociatedData(Ihandle* ih, NSView* main_view, NSView* root_view);
IupSourceDragAssociatedData* cocoaSourceDragCreateAssociatedData(Ihandle* ih, NSView* main_view, NSView* root_view);

void cocoaTargetDropDestroyAssociatedData(Ihandle* ih);
void cocoaSourceDragDestroyAssociatedData(Ihandle* ih);

/* These functions are called by the widget's NSView(DraggingDestination) implementation */
int cocoaTargetDropBasePerformDropCallback(Ihandle* ih, id<NSDraggingInfo> the_sender, NSPasteboard* paste_board, NSPoint drop_point);
NSDragOperation cocoaTargetDropBaseDraggingUpdated(Ihandle* ih, id<NSDraggingInfo> the_sender);

#endif /* __IUPCOCOA_DRAGDROP_H */
