//
//  GlyphsPathPlugin.h
//  GlyphsCore
//
//  Created by Georg Seifert on 26.04.09.
//  Copyright 2009 schriftgestaltung.de. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import <GlyphsCore/GSContainerProtocol.h>
#import <GlyphsCore/GSGlyphViewControllerProtocol.h>
#import <GlyphsCore/GSHint.h>
#import <GlyphsCore/GSSelectableElementProtocol.h>
#import <GlyphsCore/GSToolPlugin.h>
#import <GlyphsCore/GlyphsToolDrawProtocol.h>
#import <GlyphsCore/GlyphsToolEventProtocol.h>

@class GSPath;
@class GSLayer;
@class GSAnchor;
@class GSComponent;
@class GSSnapper;
@class GSGuide;
@class GSFontMaster;
@class GSColorLabelViewController;
@class GSHandle;

NS_ASSUME_NONNULL_BEGIN

#ifndef GLYPHS_LITE
#define GSSmartAnchorFlag 2001
#define GSGradientStartFlag 3001
#define GSGradientEndFlag 3002
#endif

extern NSString *GSGlyphsElementPasteboardType2;
extern NSString *GSGlyphsElementPasteboardType3;
extern NSString *GSGlyphsAttributesPasteboardType;

@class GSAlignmentZone;
/**
 A base class for all path editing tools. It handles drawing and basic path interaction

 Subclass it for custom tool plugins
 */

@interface GlyphsPathPlugin : GSToolPlugin <GlyphsToolDraw, GlyphsToolEvent, GSContainerProtocol, NSMenuDelegate, NSTextViewDelegate> {
	// BOOL hasDragged;
	BOOL _dragging;
	NSPoint _draggStart; // keep old names to not break SuperTool
	NSPoint _draggCurrent;
	NSPoint _contextClickPosition;
	// NSPoint _lastDragPosition;
	NSUInteger dragModifierFlag;
	// GSLayer *shadowLayer;
	NSMutableArray *_snappers;
	NSMutableArray<GSSnapper *> *_activeSnappers;
	NSImage *_toolBarIcon; // compatibility with older plugin
	GSLayer *_activeLayer;
	GSLayer *_foregroundLayer;
	GSFontMaster *_fontMaster;
	GSSelectableElement *_grabbedElement;
	GSSelectableElement *_highlightedElement;
	NSMutableArray *_focusOnPaths;
#if 0
	NSMutableDictionary<NSValue *, NSNumber *> *_justAddedElements;
#endif
	NSRect _selectionBounds;
	NSAffineTransform *_selectionBoundsAngle;
	NSRect _shadowSelectionBounds;
	CGFloat _interfaceScale;
	BOOL _shouldAlias;
	GSColorLabelViewController *_colorButtonsViewController;
	BOOL _isCancel;
	GSElement *_activeElement;
	NSColor *_nodeSmoothColorDefault;
	NSColor *_nodeSmoothColorDefaultDark;
	NSColor *_nodeCornerColorDefault;
	NSColor *_nodeCornerColorDefaultDark;
	NSColor *_componentColor;
	NSColor *_componentColorLocked;
	NSColor *_componentColorAligned;
	NSColor *_componentColorHorizontalAligned;
	NSColor *_componentColorDark;
	NSColor *_componentColorLockedDark;
	NSColor *_componentColorAlignedDark;
	NSColor *_componentColorHorizontalAlignedDark;
	NSColor *_zonesColorDefault;
	NSColor *_zonesColorDefaultDark;
	NSColor *_nodeSmoothColor;
	NSColor *_nodeSmoothColorDark;
	NSColor *_nodeCornerColor;
	NSColor *_nodeCornerColorDark;
	NSColor *_handleColor;
	NSColor *_zonesColor;
	NSColor *_zonesColorDark;
	NSColor *_metricsColor;

	NSColor *_gridMainColor;
	NSColor *_gridSubColor;
	NSColor *_gridMainColorDefault;
	NSColor *_gridMainColorDefaultDark;
	NSColor *_gridSubColorDefault;
	NSColor *_gridSubColorDefaultDark;

	NSTimer *_removeSnapperTimer;
	BOOL _drawDark;
}

/// The icon displayed in the toolbar.
@property (nonatomic, readonly) NSImage *toolBarIcon;
/** Yes if in a dragging state */
@property (nonatomic) BOOL dragging;

@property (nonatomic, readonly) BOOL showGuides;

/** Origin of the current dragging operation
 */
@property (nonatomic) NSPoint dragStart;

// Compatibility with plugins
@property (nonatomic) NSPoint draggStart;

/** The scaling factor for interface elements.

 On Retina displays its 1.75, otherwise 1.0
 */
@property (nonatomic, readonly) CGFloat interfaceScale;

@property (nonatomic, strong, nullable) NSArray<GSHandle *> *extraHandles;

@property (nonatomic, nullable, strong) GSSelectableElement *highlightedElement;

@property (nonatomic, strong) NSDictionary<NSValue *, NSNumber *> *justAddedElements;

#if 0
- (void)justAddedElement:(GSSelectableElement *)newElement;

- (void)justAddedElementsFromArray:(NSArray *)newElements;
#endif

/** Is called when the return key is pressed.

 Overwrite for your own behavior.
 @warning Never call that yourself.
 @param sender Typically the object that invoked this method.
 */
- (void)insertNewline:(nullable id)sender;

/** Draws the starting node of an open path

 @param node  the start or end node
 @param sel   If the node is selected or not
 @param layerOrigin The origin point of the current layer
 */
- (void)drawBegin:(GSNode *)node isSelected:(BOOL)sel atPoint:(NSPoint)layerOrigin;

- (void)drawHandlesForBounds:(NSRect)bounds atPoint:(NSPoint)layerOrigin angle:(nullable NSAffineTransform *)transform;

- (void)drawHandle:(NSPoint)point isSelected:(BOOL)selected atPoint:(NSPoint)layerOrigin;
/**
 Draws a node

 @param path     The path that contains the node
 @param idx      The index of the node
 @param selected If the node is selected or not
 @param layerOrigin    The origin point of the current layer
 */
- (void)drawHandle:(GSPath *)path atIndex:(NSUInteger)idx isSelected:(BOOL)selected atPoint:(NSPoint)layerOrigin simple:(BOOL)simple;

- (void)drawKnob:(NSPoint)point type:(GSNodeType)type selected:(BOOL)selected atPoint:(NSPoint)layerOrigin;

/** The rect that for drawing the node

 @param point		the node position
 @param selected	If the node is selected or not
 @param layerOrigin		The origin point of the current layer

 @return the rect
 */
- (NSRect)getHandleRect:(NSPoint)point isSelected:(bool)selected atPoint:(NSPoint)layerOrigin;

- (NSRect)getHandleRect:(NSPoint)point isSelected:(bool)selected size:(CGFloat)sizeScale atPoint:(NSPoint)layerOrigin;

- (void)drawGuide:(GSGuide *)guide atPoint:(NSPoint)layerOrigin selected:(BOOL)selected global:(BOOL)global;

- (void)drawHint:(GSHint *)hint atPoint:(NSPoint)layerOrigin selected:(BOOL)selected;

- (void)drawShadowAccents:(GSLayer *)layer atPoint:(NSPoint)layerOrigin;

@property (nonatomic) NSPoint transformOrigin;

- (NSRect)rectForHandle:(GSAlignment)handleIndex forBounds:(NSRect)bounds angle:(NSAffineTransform *)transform;
#ifndef GLYPHS_VIEWER

- (NSPoint)snapAtPoint:(NSPoint)point withModifier:(NSEventModifierFlags)modifierFlag;

- (void)addSnapper:(GSSnapper *)snapper;

- (void)addSnapperWithPoint:(NSPoint)point;

- (void)addActiveSnapper:(GSSnapper *)snapper;

#ifndef GLYPHS_LITE
- (NSArray *)smartAnchorsForComponent:(GSComponent *)component;
#endif

- (NSOrderedSet *)selectedObjects;

- (IBAction)selectAll:(nullable id)sender;

- (IBAction)deselectAll:(nullable id)sender;

- (void)indexPaths:(GSLayer *)layer doBackground:(BOOL *)doBackground indexPaths:(NSMutableArray *_Nonnull *_Nonnull)indexPaths layerGroup:(NSArray *_Nonnull *_Nonnull)layerGroup doAllMasters:(BOOL)doAllMasters;

#ifndef GLYPHS_LITE

- (void)autohintLayers:(NSArray *)layers;

#endif

- (void)delSelection;

- (void)delSelectionWithModifier:(NSEventModifierFlags)modifierFlag;

- (void)selectionToBackground:(id)sender;

- (IBAction)componentFromSelection:(id)sender;

- (IBAction)swapForegroundWithBackground:(id)sender;

- (nullable GSNode *)connectPathsWithNode:(GSNode *)moveNode andNode:(GSNode *)overNode;

- (GSNode *)nodeAtPoint:(NSPoint)loc atLayer:(GSLayer *)layer excludeNode:(nullable GSNode *)exclude ignoreLocked:(BOOL)ignoreLocked;

- (GSNode *)nodeAtPoint:(NSPoint)loc atLayer:(GSLayer *)layer excludeNodes:(nullable NSSet *)excludes traverseComponents:(BOOL)traverseComponents ignoreLocked:(BOOL)ignoreLocked;

- (void)transformSelection:(NSAffineTransform *)transform;

- (void)transformSelectionInLayer:(GSLayer *)layer shadowLayer:(GSLayer *)shadowLayer transform:(NSAffineTransform *)transform;

- (void)moveSelectionLayer:(GSLayer *)layer shadowLayer:(GSLayer *)shadowLayer withPoint:(NSPoint)point withModifier:(NSEventModifierFlags)modifierFlag;

- (void)moveSelectionWithPoint:(NSPoint)point withModifier:(NSEventModifierFlags)modifierFlag;

- (BOOL)setHintDraggingKnob:(GSLayer *)layer withPoint:(NSPoint)point;

- (void)drawMetricsForLayer:(GSLayer *)layer atPoint:(NSPoint)layerOrigin asActive:(BOOL)active;

- (void)editAnchorName:(GSAnchor *)anchor;

- (void)setInterpolate:(GSLayer *)layer withPoint:(NSPoint)offset;

- (nullable NSString *)selectionEPSDataFromDict:(NSDictionary *)selectedObjects;

- (IBAction)addComponent:(id)sender;

- (IBAction)addAnchor:(id)sender;

#ifndef GLYPHS_LITE
- (IBAction)autohint:(id)sender;

- (IBAction)dehint:(id)sender;
#endif

- (IBAction)addVHint:(id)sender;

- (IBAction)addHHint:(id)sender;

- (nullable NSArray *)addHintsForNodes:(NSMutableArray *)nodes toLayer:(GSLayer *)layer vertical:(BOOL)vertical type:(GSHintType)type position:(NSPoint)position;

- (NSSet *)touchedByHintsIndexes:(GSLayer *)layer;

- (IBAction)addGuide:(id)sender;

- (IBAction)reversePaths:(id)sender;

- (IBAction)checkConnections:(id)sender;

- (IBAction)addExtremes:(id)sender;

- (IBAction)alignPoints:(id)sender;
#endif
#ifndef GLYPHS_LITE
@property (assign) int findSubpathIndex;
@property (assign) int findSubpathCount;
- (void)setFindPathsPasteboard:(GSPath *)path;

- (IBAction)makeNodeFirstForAll:(id)sender;
- (IBAction)makeNodeFirst:(id)sender;
- (IBAction)focusOnSelectedPaths:(id)sender;
- (IBAction)clearFocusOnPaths:(id)sender;
#endif
@end

NS_ASSUME_NONNULL_END
