#ifndef __IUPCOCOA_DRAGDROP_H 
#define __IUPCOCOA_DRAGDROP_H

#import <Cocoa/Cocoa.h>

#include <stdbool.h>
#include "iup.h"

extern const void* _Nonnull IUPSOURCEDRAG_ASSOCIATED_OBJ_KEY;
extern const void* _Nonnull 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 operating on
@property(nonatomic, assign) NSView* mainView;
@property(nonatomic, assign) NSView* rootView;

@end

@interface IupSourceDragAssociatedData : NSObject <NSDraggingSource, NSPasteboardTypeOwner, NSPasteboardItemDataProvider, NSFilePromiseProviderDelegate>
@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;
// TODO: Can we support multiple types via DataProvider?
//@property(nonatomic, copy) NSString* dragRegisteredType;
@property(nonatomic, copy) NSArray<NSString*>* dragRegisteredTypes;
//@property(nonatomic, copy) NSArray* dropRegisteredTypes;
@property(nonatomic, assign) bool useAutoBeginDrag;
@property(nonatomic, assign) bool useAutoGenerateDragImage;
@property(nonatomic, copy) NSString* defaultFilePromiseName; // used for when the user doesn't define a callback. Intended for when we design our own widgets with built-in behaviors, like IupCanvas.
//@property(nonatomic, assign) bool wantsFilePromise;
// helper: true if (user's) wantsFilePromise OR CALLBACK is set
- (bool) usesFilePromise;
- (bool) hasFilePromiseCallback;

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

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

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


- (NSDraggingItem*) defaultDraggingItem;
- (NSPasteboardItem*) defaultPasteboardItem;


// @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 * __nullable errorOrNil))completion_handler;

- (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);

int cocoaTargetDropBasePerformDropCallback(Ihandle* ih, id<NSDraggingInfo> the_sender, NSPasteboard* paste_board, NSPoint drop_point);

#endif /* __IUPCOCOA_DRAGDROP_H */

