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

#import <GlyphsCore/GSElement.h>

@class GSNode;
/**
 Hint types
 */

typedef NS_ENUM(int8_t, GSHintType) {
	/** Tag */
	GSHintTypeTag = -2,
	/** TopGhost for PS hints */
	GSHintTypeTopGhost = -1,
	/** Stem for PS hints */
	GSHintTypeStem = 0,
	/** BottomGhost for PS hints */
	GSHintTypeBottomGhost = 1,
	/** Flex */
	GSHintTypeFlex = 2,
	/** Snap for TT hints */
	GSHintTypeTTSnap = 3,
	/** Stem for TT hints */
	GSHintTypeTTStem = 4,
	/** Shift for TT hints */
	GSHintTypeTTShift = 5,
	/** Interpolation for TT hints */
	GSHintTypeTTInterpolate = 6,
	/** Diagonal for TT hints */
	GSHintTypeTTDiagonal = 8,
	/** Delta hints */
	GSHintTypeTTDelta = 9,
	/** Corner Component */
	GSHintTypeCorner = 16,
	/** Cap Component */
	GSHintTypeCap = 17,
	/** Brush */
	GSHintTypeBrush = 18,
	/** Line */
	GSHintTypeSegment = 19,
	/** Head */
	GSHintTypeHead = 20,
	/** Auto */
	GSHintTypeAuto = 0x7f,
};

extern const CGFloat GSHintTopGhostWidth;
extern const CGFloat GSHintBottomGhostWidth;

typedef NS_ENUM(uint8_t, GSHintStates) {
	GSHintStatesOK,
	GSHintStatesTooSmall,
	GSHintStatesFail,
};

typedef NS_OPTIONS(uint32_t, GSHintOptions) {
	/// Scales a cap component to fit between its attachment points.
	GSHintOptionTTDontRound NS_SWIFT_NAME(trueTypeRoundingStateNone) = 4,
	GSHintOptionTTRound NS_SWIFT_NAME(trueTypeRoundingStateRound) = 0,
	GSHintOptionTTRoundUp NS_SWIFT_NAME(trueTypeRoundingStateRoundUp) = 1,
	GSHintOptionTTRoundDown NS_SWIFT_NAME(trueTypeRoundingStateRoundDown) = 2,
	GSHintOptionTTRoundAuto NS_SWIFT_NAME(trueTypeRoundingStateAuto) = 8,
	GSHintOptionFit NS_SWIFT_NAME(fit) = 8,
	GSHintOptionTriple NS_SWIFT_NAME(trueTypeTriple) = 128,
} NS_SWIFT_NAME(GSHint.Options);

extern const unsigned int GSHintOriginLSBIndex;
extern const unsigned int GSHintOriginRSBIndex;

NS_ASSUME_NONNULL_BEGIN

FOUNDATION_EXPORT NSString *const GSHighlightPath;
FOUNDATION_EXPORT NSString *const GSCornerMidPoint;

@interface GSHint : GSElement <NSCoding, NSCopying> {
  @public
	NSUInteger _ttOriginIndex;
	NSUInteger _ttTargetIndex;
	NSUInteger _ttOtherIndex1;
	NSUInteger _ttOtherIndex2;
}

/// More specifically typed convenience getter for the generic `parent` property declared by `GSShape`.
@property (weak, nonatomic, nullable, readonly) GSLayer *parentLayer;

@property (nonatomic) CGFloat origin;
@property (nonatomic) CGFloat width;
@property (nonatomic) BOOL horizontal;
@property (strong, nullable) GSNode *originNode;
@property (strong, nonatomic, nullable) GSNode *targetNode;
@property (strong, nonatomic, nullable) GSNode *otherNode1;
@property (strong, nonatomic, nullable) GSNode *otherNode2;
@property (strong, nonatomic, nullable) NSIndexPath *originIndex;
@property (strong, nonatomic, nullable) NSIndexPath *targetIndex;
@property (strong, nonatomic, nullable) NSIndexPath *otherIndex1;
@property (strong, nonatomic, nullable) NSIndexPath *otherIndex2;
@property (nonatomic) GSHintType type;
@property (nonatomic) NSRect badgeRect;
@property (strong, nonatomic) NSString *badgeString;
@property (nonatomic) NSPoint originKnob;
@property (nonatomic) NSPoint targetKnob;
@property (nonatomic) NSPoint otherKnob1;
@property (nonatomic) NSPoint otherKnob2;

@property (nonatomic) int selection;
@property (nonatomic) NSInteger stem;
@property (nonatomic, strong, nullable) NSString *name;
@property (nonatomic) uint32_t options;
@property (nonatomic) NSPoint scale;
@property (nonatomic, strong, nullable) NSDate *lastUpdate;

- (instancetype)initWithDict:(nonnull NSDictionary *)hintDict format:(GSFormatVersion)formatVersion;

- (instancetype)initWithType:(GSHintType)type horizontal:(BOOL)horizontal origin:(CGFloat)origin width:(CGFloat)width;

- (instancetype)initWithType:(GSHintType)type horizontal:(BOOL)horizontal originIndex:(NSIndexPath *)origin targetIndex:(nullable NSIndexPath *)target;

- (BOOL)isEqualToHint:(GSHint *)other;

- (void)makeGhost;

- (void)save;

- (void)restore;

- (BOOL)updateIndexes;

- (void)updateSize;

- (nullable NSSet *)dependenIndexes;

- (nullable NSSet *)touchingIndexes;

- (nullable NSSet *)touchingIndexesAlreadyTouched:(nonnull NSSet *)alreadyTouchedIndexes;

@property (nonatomic, readonly) BOOL isTrueType;

@property (nonatomic, readonly) BOOL isPostScript;

@property (nonatomic, readonly) BOOL isPathComponent;
@property (nonatomic, readonly) BOOL isCorner GSDeprecated("isPathComponent");

@property (nonatomic, readonly) NSString *typeName;

/// localized version of typeName
@property (nonatomic, readonly) NSString *typeNameUI;

@property (nonatomic) GSElementAttachment alignment;

@property (nonatomic, strong, nullable) NSDictionary *settings;

- (nullable id)objectInSettingsForKey:(nullable NSString *)key;

- (void)setObjectInSettings:(nullable id)value forKey:(nullable NSString *)key;

+ (nullable NSIndexPath *)indexPathForNode:(GSNode *)node inLayer:(GSLayer *)layer;

+ (nullable NSIndexPath *)indexPathForPosition:(NSPoint)aPoint inLayer:(GSLayer *)layer tolerance:(CGFloat)tolerance actualPosition:(nullable NSPoint *)actualPosition flag:(int)flag;

+ (nullable NSIndexPath *)indexPathsForInflection:(NSPoint)aPoint inLayer:(GSLayer *)layer tolerance:(CGFloat)tolerance actualPosition:(nullable NSPoint *)actualPosition;

+ (nullable NSIndexPath *)indexPathFromPlist:(NSString *)string;

+ (nullable GSNode *)nodeForIndexPath:(NSIndexPath *)indexPath unlimited:(BOOL)unlimited layer:(GSLayer *)layer;

+ (nullable GSHint *)doubleCornerOfType:(GSHintType)cornerType firstNode:(GSNode *)firstNode secondNode:(GSNode *)secondNode layer:(GSLayer *)layer;

+ (GSHintType)typeForName:(NSString *)typeName;

- (void)adjustToFlippedPath:(BOOL)reversed;

+ (void)sortHints:(NSMutableArray *)hints;

- (void)reverse;

- (nullable NSBezierPath *)highlightPathForScale:(CGFloat)scale state:(GSHintStates *)state;
- (nullable NSBezierPath *)highlightPathForScale:(CGFloat)scale;

- (NSString *)hintString;

- (NSString *)hintKey;

@end

NS_ASSUME_NONNULL_END
