//
//  GSPathSegment.h
//  PathOperations
//
//  Created by Georg Seifert on 03.03.14.
//  Copyright (c) 2014 Georg Seifert. All rights reserved.
//

@class FTPointArray;

#import <GlyphsCore/GSNode.h>
#import <GlyphsCore/GSPenProtocol.h>

#define maxElements 40

typedef enum : uint8 {
	GSSegmentOptionWhite = 1 << 1,
	GSSegmentOptionOpenPath = 1 << 2,
	GSSegmentOptionHasSimpleBounds = 1 << 3,
	GSSegmentOptionIsFlat = 1 << 4,
} GSSegmentOptions;

typedef struct {
	NSPoint elements[4];
	uint8 count;
	GSNodeType type;
	GSSegmentOptions options;
	NSRect bounds;
} GSSegmentStruct;

void _GSSegmentUpdateBounds(GSSegmentStruct *S);

double GSCalculateErrorLength(double curveLength, double inputError);

@interface GSPathSegment : NSObject <NSCopying> {

  @public
	int flag;
	GSNodeType type;
	uint8 count;
	GSSegmentOptions options;
	NSPoint elements[maxElements];
	NSRect bounds;
}
@property (nonatomic) GSNodeType type;
@property (nonatomic) uint8 countOfPoints;
@property (nonatomic, assign) int flag;
@property (strong, nonatomic) NSArray *objects;

- (instancetype)initWithLinePoint1:(NSPoint)P1 point2:(NSPoint)P2 options:(GSSegmentOptions)options;
- (instancetype)initWithCurvePoint1:(NSPoint)P1 point2:(NSPoint)P2 point3:(NSPoint)P3 point4:(NSPoint)P4 options:(GSSegmentOptions)options;
- (instancetype)initWithDescription:(NSString *)string;
- (instancetype)initWithQCurve:(NSArray *)points;
- (instancetype)initWithQCurve:(NSPoint *)points count:(int)count;
- (instancetype)initWithSegmentStruct:(GSSegmentStruct *)S;
- (GSSegmentStruct)segmentStruct;
- (NSRect)bounds;
- (void)updateBounds;
- (NSComparisonResult)compare:(GSPathSegment *)otherObject italicAngle:(CGFloat)italicAngle;
- (void)reverse;
- (NSComparisonResult)compare:(GSPathSegment *)otherObject;
- (BOOL)isEqualToSegment:(GSPathSegment *)otherSegment;
- (BOOL)isEqualToSegment:(GSPathSegment *)otherSegment tolerance:(CGFloat)tolerance;
- (NSPoint)middlePoint;
- (NSPoint)middlePointRight;
#if 0
- (NSPoint)middlePointLeft;
#endif
- (NSPoint)lastPoint;
- (void)splitAtTime:(CGFloat)t firstHalf:(GSPathSegment **)left secondHalf:(GSPathSegment **)right;
- (FTPointArray *)intersectionPoints:(GSPathSegment *)otherSegment;
- (FTPointArray *)intersectionPoints:(GSPathSegment *)otherSegment unlimited:(BOOL)unlimited;
- (NSArray *)inflectionPoints;
- (NSPoint)pointAtIndex:(NSUInteger)idx;
- (void)setPoint:(NSPoint)p atIndex:(NSUInteger)idx;
- (CGFloat)curvatureAtTime:(CGFloat)t;
- (NSPoint)pointAtTime:(CGFloat)t;
- (NSPoint)normalAtTime:(CGFloat)t;
- (CGFloat)tangentAtTime:(CGFloat)t;
- (NSArray *)extremePoints;
- (NSArray *)extremeTimes NS_RETURNS_RETAINED;
- (CGFloat)length;
- (CGFloat)lengthFast;
- (BOOL)normalizeHandles;
- (void)drawInPen:(NSObject<GSPenProtocol> *)pen;
- (NSString *)descriptionWithPrecision:(int)precision;

#ifndef GLYPHS_VIEWER
/**
 is used in makeCorner and offset paths to connect the segments when there is a gap

 @param otherSegment otherSegment
 @param force if YES, it used a less precise geometry
 @param miterLimit the miter limit
 @param newPoint on return, the position of the connection
 @return returns YES if a connection was found
 */
- (BOOL)connectWithSegment:(GSPathSegment *)otherSegment force:(BOOL)force miterLimit:(CGFloat)miterLimit newPoint:(NSPoint *)newPoint;

- (GSPathSegment *)lineSegmentCurveError:(CGFloat)curveError NS_RETURNS_RETAINED;

- (GSPathSegment *)oneQuadraticSegmentCurveError:(CGFloat)curveError NS_RETURNS_RETAINED;

- (GSPathSegment *)twoQuadraticSegmentCurveError:(CGFloat)curveError NS_RETURNS_RETAINED;

- (GSPathSegment *)threeQuadraticSegmentCurveError:(CGFloat)curveError NS_RETURNS_RETAINED;

- (GSPathSegment *)convertToQuadraticWithCurveError:(CGFloat)curveError NS_RETURNS_RETAINED;
#endif

@end
