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

#import <Cocoa/Cocoa.h>
#import <GlyphsCore/GSElement.h>

@class GSNode;
/**
 Hint types
 */

typedef NS_ENUM(int8_t, GSHintType) {
	/** Tag */
	Tag = -2,
	/** TopGhost for PS hints */
	TopGhost = -1,
	/** Stem for PS hints */
	Stem = 0,
	/** BottomGhost for PS hints */
	BottomGhost = 1,
	/** Flex */
	Flex = 2,
	/** Snap for TT hints */
	TTSnap = 3,
	/** Stem for TT hints */
	TTStem = 4,
	/** Shift for TT hints */
	TTShift = 5,
	/** Interpolation for TT hints */
	TTInterpolate = 6,
	/** Diagonal for TT hints */
	TTDiagonal = 8,
	/** Delta hints */
	TTDelta = 9,
	/** Corner Component */
	GSCorner = 16,
	/** Cap Component */
	GSCap = 17,
	/** Brush */
	GSBrush = 18,
	/** Line */
	GSSegment = 19,
	/** Auto */
	Auto = 0x7f,
};

/** Hint Options */
typedef NS_ENUM(uint8_t, GSHintOptions) {
	TTDontRound = 4,
	TTRound = 0,
	TTRoundUp = 1,
	TTRoundDown = 2,
	TTRoundAuto = 8,
	Trippel = 128,
};

#ifndef hintOriginLSBIndex
#define hintOriginLSBIndex 0x1fffe
#define hintOriginRSBIndex 0x1ffff
#endif

NS_ASSUME_NONNULL_BEGIN

@interface GSHint : GSElement <NSCoding, NSCopying> {

	GSNode *_originNode;
	GSNode *_targetNode;
	GSNode *_otherNode1;
	GSNode *_otherNode2;
	NSIndexPath *_originIndex;
	NSIndexPath *_targetIndex;
	NSIndexPath *_otherIndex1;
	NSIndexPath *_otherIndex2;

	GSHintType _type;
	NSRect _badgeRect;
	NSPoint _originKnob;
	NSPoint _targetKnob;
	NSPoint _otherKnob1;
	NSPoint _otherKnob2;
	int _selection;
	NSInteger _stem;
	NSString *_name;
	uint32_t _options;
	NSDate *_lastUpdate;
	NSMutableDictionary *_settings;
  @public
	NSUInteger _ttOriginIndex;
	NSUInteger _ttTargetIndex;
	NSUInteger _ttOtherIndex1;
	NSUInteger _ttOtherIndex2;
	CGFloat _origin;
	CGFloat _width;
	NSPoint _scale;
	BOOL _horizontal;
	CGFloat _rotate;
	GSComponentAlignment _alignment;
}

/// 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, nonatomic, 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;

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

- (void)makeGhost;

- (void)save;

- (void)restore;

- (BOOL)updateIndexes;

- (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 isCorner;
/// For compatibility with the future.
@property (nonatomic, readonly) BOOL isPathComponent;

- (NSString *)typeName;

/// localized version of typeName
- (NSString *)typeNameUI;

@property (nonatomic) GSElementOrientation 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:(nullable GSNode *)node inLayer:(nullable GSLayer *)layer;

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

+ (nullable NSIndexPath *)indexPathsForInflection:(NSPoint)aPoint inLayer:(nullable 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;

#pragma mark TempData
/**
 a  dictionary that stores data. It will not be written to disk.
 */
@property (nonatomic, strong, nullable) NSDictionary *tempData;

/**
 Adds key/value to tempData. Pass nil as value to remove previous set data

 @param value and object or nil
 @param key the key
 */
- (void)setTempData:(nullable id)value forKey:(nonnull NSString *)key;

/**
 return value for key in tempData

 @param key the key
 @return a value or nil
 */
- (nullable id)tempDataForKey:(nonnull NSString *)key;

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

- (void)reverse;

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

#if DEBUG
- (NSString *)hintKey;
#endif

@end

NS_ASSUME_NONNULL_END
