//
//  MPSuperPopoverController
//
//
//  Created by Kirill Kovalenko on 11.05.16.
//  Copyright © 2016 Macphun. All rights reserved.
//

#import <Cocoa/Cocoa.h>

#import "MPSuperPopoverControllerDefines.h"

extern NSString *_Nonnull const kMPSuperPopoverDidShow;
extern NSString *_Nonnull const kMPSuperPopoverDidClose;

@class MPSuperPopoverWindow;


@protocol MPSuperPopoverControllerDelegate, MPSuperPopoverControllerDataSource;


@interface MPSuperPopoverController : NSObject

#pragma mark -
#pragma mark Properties

@property (nonatomic, strong, nullable) id <MPSuperPopoverControllerDelegate> delegate;
@property (strong, nonatomic, nullable) NSObject <MPSuperPopoverControllerDataSource> *dataSource;

@property (nonatomic, strong, nonnull) NSColor *color;
@property (nonatomic, strong, nonnull) NSColor *borderColor;
@property (nonatomic, strong, nonnull) NSColor *topHighlightColor;
@property (nonatomic, assign) CGFloat borderWidth;
@property (nonatomic, assign) CGFloat cornerRadius; // Default value: 4
@property (nonatomic, assign) NSSize arrowSize; // Default value: {23, 12}
@property (nonatomic, assign, readonly) MPSuperPopoverArrowDirection arrowDirection;
@property (nonatomic, assign) ShadowSettings shadowSettings;
@property (nonatomic, assign) BOOL blurBackground;
@property (nonatomic, assign) BOOL customUnblurredBackground;
@property (nonatomic, assign) NSEdgeInsets contentEdgeInsets;
@property (nonatomic, assign) NSEdgeInsets popoverOffsetsFromPositionView;
@property (nonatomic, assign) NSPoint popoverOffset;
@property (nonatomic, assign) BOOL alignWithFromViewEdge;

/** The size of the content of the popover. This is automatically set to contentViewController's size when the view controller is set, but can be modified. Changes to this value are animated when animates is set to YES **/
@property (nonatomic, assign) NSSize contentSize;

@property (nonatomic, assign) BOOL closesWhenEscapeKeyPressed;
@property (nonatomic, assign) BOOL closesWhenPopoverResignsKey;
@property (nonatomic, assign) BOOL closesWhenApplicationBecomesInactive;
@property (nonatomic, assign) BOOL animates;
@property (nonatomic, assign) MPSuperPopoverAnimationType animationType; // Default value: `MPSuperPopoverAnimationTypePop`
@property (nonatomic, strong, nonnull) NSViewController *contentViewController;

@property (nonatomic, strong, readonly, nonnull) NSView *fromView;
@property (nonatomic, strong, readonly, nonnull) MPSuperPopoverWindow *popoverWindow;
@property (nonatomic, assign, readonly) BOOL popoverIsVisible;
@property (nonatomic, assign) BOOL showArrow;

/*!
 * @brief flag for skipping handling of mouse and key events
 */
@property (assign, nonatomic) BOOL skipMouseAndKeyEventsHandling;

/*!
 * @brief flag for control popover's local monitor for NSMouseMovedMask, NSMouseEnteredMask, NSScrollWheelMask that blocks all events from other windows
 */
@property (assign, nonatomic) BOOL blockMouseMoveEventsForOtherWindows;

/*!
 * @brief flag that determines if arrow cursor should be displayed inside a popover
 */
@property (assign, nonatomic) BOOL arrowCursorEnabled;

@property (assign, nonatomic) BOOL disableParentWindowCursorRects;

@property (nonatomic, copy, nullable) void(^closeCallback)();

/// Pass YES if the popover should be presented from modal window.
- (void)enablePresentingFromModalWindow:(BOOL)enable;

#pragma mark -
#pragma mark Methods

- (id _Nonnull)initWithContentViewController:(NSViewController * _Nonnull)viewController withOwnerWindow:(NSWindow * _Nonnull)window;
- (void)presentPopoverFromRect:(NSRect)rect inView:(NSView * _Nonnull)positionView withEvent:(NSEvent* _Nullable)event preferredArrowDirection:(MPSuperPopoverArrowDirection)directions anchorsToPositionView:(BOOL)anchors;
- (void)presentPopoverFromRect:(NSRect)rect inView:(NSView * _Nonnull)positionView preferredArrowDirection:(MPSuperPopoverArrowDirection)directions anchorsToPositionView:(BOOL)anchors;

/** 
 Recalculates the best arrow direction for the current window position and resets the arrow direction. The change will not be animated. **/
- (void)recalculateAndResetArrowDirection;

/**
 Closes the popover unless NO is returned for the -popoverShouldClose: delegate method 
 @param sender the object that sent this message
 */
- (IBAction)closePopover:(id _Nullable)sender;

/**
 Closes the popover regardless of what the delegate returns
 @param sender the object that sent this message
 */
- (IBAction)forceClosePopover:(id _Nullable)sender;

/**
 Returns the frame for a popop window with a given size depending on the arrow direction.
 @param contentSize the popover window content size
 @param direction the arrow direction
 */
- (NSRect)popoverFrameWithSize:(NSSize)contentSize arrowDirection:(MPSuperPopoverArrowDirection)direction;

@end

@protocol MPSuperPopoverControllerDelegate <NSObject>
@optional
/**
 When the -closePopover: method is invoked, this method is called to give a change for the delegate to prevent it from closing. Returning NO for this delegate method will prevent the popover being closed. This delegate method does not apply to the -forceClosePopover: method, which will close the popover regardless of what the delegate returns.
 @param popover the @class MPSuperPopoverController object that is controlling the popover
 @returns whether the popover should close or not
 */
- (BOOL)popoverShouldClose:(MPSuperPopoverController * _Nonnull)popover;

/**
 Invoked right before the popover shows on screen
 @param popover the @class MPSuperPopoverController object that is controlling the popover
 */
- (void)popoverWillShow:(MPSuperPopoverController * _Nonnull)popover;

/**
 Invoked right after the popover shows on screen
 @param popover the @class MPSuperPopoverController object that is controlling the popover
 */
- (void)popoverDidShow:(MPSuperPopoverController * _Nonnull)popover;

/**
 Invoked right before the popover closes
 @param popover the @class MPSuperPopoverController object that is controlling the popover
 */
- (void)popoverWillClose:(MPSuperPopoverController * _Nonnull)popover;

/**
 Invoked right after the popover closes
 @param popover the @class MPSuperPopoverController object that is controlling the popover
 */
- (void)popoverDidClose:(MPSuperPopoverController * _Nonnull)popover;
@end


@protocol  MPSuperPopoverControllerDataSource <NSObject>
@optional

- (NSRect)selectedItemRectForSuperPopover:(MPSuperPopoverController * _Nonnull)superPopover;

@end

@interface NSWindow (SuperPopoverController)
- (MPSuperPopoverController * _Nullable)popoverControllerIfAvailable;
@end
