//
//  GSOffsetCurve.h
//  GlyphsCore
//
//  Created by Florian Pircher on 30.11.23.
//  Copyright © 2023 schriftgestaltung.de. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <GlyphsCore/GSPath.h>

NS_ASSUME_NONNULL_BEGIN

@class GSMetricStore;
@class GSPenPoint;
@class GSPathSegment;

#ifndef GLYPHS_LITE
extern NSString *const GSWidthBucketsKey;

void GSComputeWidthSamplesFromExplicitPenPoints(NSArray<GSPathSegment *> *segments, GSPath *path);
#endif

void GSPositionOffset(CGFloat *offset, CGFloat position, BOOL reverse);

GSPenPoint *GSPenPointWithDefaultValue(GSPenPoint *penPoint, GSPath *path);

NSPoint GSComputePenPoint(GSPenPoint *s, GSPathSegment * _Nonnull seg, BOOL leftSide, NSPoint *_Nullable pathPoint);

double GSCalculateFactorFromUnitVector(CGPoint unitVector);

BOOL GSOffsetCurveSegment(NSPoint *P0, NSPoint *P1, NSPoint *P2, NSPoint *P3, CGFloat offsetX, CGFloat offsetY);

BOOL GSOffsetCurveSegmentUneven(NSPoint *P0, NSPoint *P1, NSPoint *P2, NSPoint *P3, CGFloat offsetX1, CGFloat offsetY1, CGFloat offsetX2, CGFloat offsetY2, CGFloat angleIn, CGFloat angleOut);

BOOL GSFineTuneCurve(NSPoint P0, NSPoint *P1, NSPoint *P2, NSPoint P3, NSPoint original0, NSPoint original1, NSPoint original2, NSPoint original3, CGFloat offsetX, CGFloat offsetY);

// BOOL GSFineTuneCurveUneven(NSPoint P0, NSPoint *P1, NSPoint *P2, NSPoint P3, NSPoint original0, NSPoint original1, NSPoint original2, NSPoint original3, CGFloat offsetX1, CGFloat offsetY1, CGFloat offsetX2, CGFloat offsetY2, CGFloat angleIn, CGFloat angleOut);

@interface GSOffsetCurve : NSObject

/// - Parameter path: A `GSPath` or `NSBezierPath` since `NSBezierPath` also implements the relevant methods (assuming the `NSBezierPath` contains only a single subpath).
/// - Parameter position: `-1`: left of path, `0`: centered on path, `1`: right of path
+ (NSArray<GSPath *> *)offsetPath:(id<GSDrawPath>)path
						  offsetX:(CGFloat)offsetX
						  offsetY:(CGFloat)offsetY
					   makeStroke:(BOOL)makeStroke
						 position:(CGFloat)position
							angle:(CGFloat)angle
					capStyleStart:(GSLineCapStyle)capStyleStart
					  capStyleEnd:(GSLineCapStyle)capStyleEnd
							 join:(GSLineJoinStyle)join
					  italicAngle:(CGFloat)italicAngle
							 grid:(GSGridSettings)grid
		   keepCompatibleOutlines:(BOOL)keepCompatible
					 extraHandles:(nullable NSMutableArray *)extraHandles;

/// - Parameter position: `-1`: left of path, `0`: centered on path, `1`: right of path
+ (NSInteger)offsetLayer:(GSLayer *)layer
				 offsetX:(CGFloat)offsetX
				 offsetY:(CGFloat)offsetY
			  makeStroke:(BOOL)makeStroke
			  autoStroke:(BOOL)autoStroke
				position:(CGFloat)pos
				   angle:(CGFloat)angle
				 metrics:(nullable NSArray<GSMetricStore *> *)metrics
				   error:(NSError **)error
				  shadow:(nullable GSLayer *)shadowLayer
		   capStyleStart:(GSLineCapStyle)capStyleStart
			 capStyleEnd:(GSLineCapStyle)capStyleEnd
					join:(GSLineJoinStyle)join
  keepCompatibleOutlines:(BOOL)keepCompatible;

+ (void)connectOffsetSegments:(NSMutableArray<GSPathSegment *> *)segments closed:(BOOL)closed join:(GSLineJoinStyle)join limitX:(CGFloat)offsetX limitY:(CGFloat)offsetY keepCompatibleOutlines:(BOOL)keepCompatible extraHandles:(nullable NSMutableArray *)extraHandles;

+ (NSArray <GSPathSegment *> *)offsetSegment:(GSPathSegment *)segment offsetX:(CGFloat)offsetX offsetY:(CGFloat)offsetY position:(CGFloat)pos angle:(CGFloat)angle reverse:(BOOL)reverse;

@end

NS_ASSUME_NONNULL_END
