/** \file GSNode.h */
//
//  GSNode.h
//  GlyphsCore
//
//  Created by Georg Seifert on 05.04.09.
//  Copyright 2009 schriftgestaltung.de. All rights reserved.
//

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

NS_ASSUME_NONNULL_BEGIN

@class GSPath;

/**
 An enumeration of node and connection types.
 */
typedef NS_ENUM(uint8_t, GSNodeType) {
	/// Move
	MOVE NS_SWIFT_NAME(move) = 17,
	/// Line
	LINE NS_SWIFT_NAME(line) = 1,
	/// Curve
	CURVE NS_SWIFT_NAME(cubicCurve) = 35,
	/// Offcurve
	OFFCURVE NS_SWIFT_NAME(offCurve) = 65,
	/// Quadratic curve
	QCURVE NS_SWIFT_NAME(quadraticCurve) = 36,
	HOBBYCURVE NS_SWIFT_NAME(hobbyCurve) = 37,
	/// Sharp connection
	SHARP NS_SWIFT_NAME(sharp) = 0,
	/// Smooth connection
	SMOOTH NS_SWIFT_NAME(smooth) = 100,
	SPECIAL NS_SWIFT_NAME(special) = 101,
	TANGENTSMOOTH NS_SWIFT_NAME(tangentSmooth) = 102
} NS_SWIFT_NAME(GSNode.NodeType);

// For compatibility with the future:

static const GSNodeType GSNodeTypeMove = MOVE;
static const GSNodeType GSNodeTypeLine = LINE;
static const GSNodeType GSNodeTypeCubicCurve = CURVE;
static const GSNodeType GSNodeTypeOffCurve = OFFCURVE;
static const GSNodeType GSNodeTypeQuadraticCurve = QCURVE;
static const GSNodeType GSNodeTypeHobbyCurve = HOBBYCURVE;

static const GSNodeType GSNodeConnectionSharp = SHARP;
static const GSNodeType GSNodeConnectionSmooth = SMOOTH;
static const GSNodeType GSNodeConnectionSpecial = SPECIAL;
static const GSNodeType GSNodeConnectionTangentSmooth = TANGENTSMOOTH;

typedef GSNodeType GSNodeConnection NS_SWIFT_NAME(GSNode.Connection);

/** The class defining the node object

 It is a subclass of GSElement
 */
@interface GSNode : GSElement <NSCoding, NSCopying, GSUserDataProtocol> {
	NSMutableDictionary *_userData;
  @public
	GSNodeType _type;
	GSNodeType _connection;
}

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

/// node type
@property (assign, nonatomic) GSNodeType type;
@property (readonly) char typeTag;

- (CFStringRef)elementString CF_RETURNS_RETAINED;

- (instancetype)initWithArray:(NSArray *)list format:(GSFormatVersion)formatVersion;

- (instancetype)initWithElementString:(NSString *)elementString;

- (BOOL)isEqualToNode:(GSNode *)other;

- (BOOL)canAttachCorner;

- (void)setTypeFast:(GSNodeType)type;
/**
 convenient init

 @param position the position
 @param type the type of the node (LINE, CURVE, QCURVE)
 @param connection the connection (SMOOTH, SHARP)
 */
- (instancetype)initWithPosition:(NSPoint)position type:(GSNodeType)type connection:(GSNodeType)connection;

/// connection type
@property (assign, nonatomic) GSNodeType connection;

/// convenience to simplify checking the connection.
@property (readonly) BOOL isSmooth;

/** toggles the connection type between SHARP and SMOOTH */
- (void)toggleConnection:(BOOL)makeSmooth;

/// automatically set the connection for handle depending on the angle
- (void)checkConnection;

/** Convenient method to make this the first node in the path.*/
- (void)makeNodeFirst;

- (NSUInteger)nodeIndex;

- (nullable GSNode *)nextOncurveNode;
- (nullable GSNode *)previousOncurveNode;
@end
NS_ASSUME_NONNULL_END
