//
//  GSPath.h
//  FontBezier Doc
//
//  Created by Georg Seifert on 19.10.05.
//  Copyright 2005 schriftgestaltung.de. All rights reserved.
//

#import <Cocoa/Cocoa.h>
@class GSNode;
@class GSGlyph;
@class GSLayer;
@class GSElement;
static inline NSArray * GSMakeCurveSegment(NSPoint P1, NSPoint P2, NSPoint P3, NSPoint P4);
static inline NSArray * GSMakeCurveSegment(NSPoint P1, NSPoint P2, NSPoint P3, NSPoint P4) {
	return [NSArray arrayWithObjects:[NSValue valueWithPoint:P1],
									 [NSValue valueWithPoint:P2],
									 [NSValue valueWithPoint:P3],
									 [NSValue valueWithPoint:P4], nil];
}
static inline NSArray * GSMakeLineSegment(NSPoint P1, NSPoint P2);
static inline NSArray * GSMakeLineSegment(NSPoint P1, NSPoint P2) {
	return [NSArray arrayWithObjects:[NSValue valueWithPoint:P1],
									 [NSValue valueWithPoint:P2], nil];
}

typedef enum {
	GSCounterClockWise = -1,
	GSClockWise = 1
} GSPathDirection;

/** The class defining the path object */

@interface GSPath : NSObject <NSCoding, NSCopying> {
	NSMutableArray *_nodes;
	BOOL closed;
	GSLayer * parent;
}
/// A Pointer to the containing GSLayer object
@property(assign, nonatomic) GSLayer * parent;

/// An array of GSNode objects.
@property(retain, nonatomic) NSArray *nodes;

/// Set if the path is closed.
@property (nonatomic) BOOL closed;

/** initializes a path with a dictionary loaded from a pList.
 @param pathDict A dictionary
 */
- (id) initWithPathDict:(NSDictionary *) pathDict;

/// Returns the content of the path to store in pList. 
- (NSDictionary*) pathDict;

- (BOOL) saveToFile:(FILE*) File error:(NSError**) error ;

/** gives the neares Point on the path

 @return the integer part of the return value is the Index of the next oncurve point. The fractional digits contain the time to the point.
 */
- (NSPoint) nearestPointOnPath:(NSPoint) aPoint pathTime:(CGFloat*) PathTime;
- (NSPoint) pointAtPathTime:(CGFloat) PathTime ;
/** Tests if pt lays on the path and than inserts a new point and corrects the handles of the other points to preseve the paths appearence.

 @param Point The point on where to insert a new point.
 @return If the new point object, or nil if something went wrong.
 */
- (GSNode *) insertNodeWithPathTime:(CGFloat) PathTime ;
/** Adds the node to the end of the paths array.

 @param Node The node to add.
 */
- (void) addNode:(GSNode *) Node ;

/** Inserts \a Node at the \a Index into \a paths.

 @param Node The node to insert.
 @param Index The index in the receiver at which to insert the Node. This value must not be greater than the count of nodes in the path.
 */
- (void) insertNode:(GSNode *) Node atIndex:(NSInteger) Index ;

- (void) appendPath:(GSPath*) Path ;
/** removes the point at \a Index from \a paths.

 @param Index The index of the node to remove.
 */
- (void) removeNodeAtIndex:(NSInteger) Index ;

/** Removes \a Node from \a paths.

 @param Node The node to return from the path.
 */
- (void) removeNode:(GSNode *) Node ;

/** Removes \a Node and tries to keep the shape of the path.

 e.g. If Node is a offcurve node, it removes the second offcurve node and sets the segment to LINE.
 @param Node The node to return from the path.
 */
- (void) removeNodeCheckKeepShape:(GSNode *) Node ;

/** Removes \a Node.

 If Node is a offcurve node, it removes the second offcurve node and sets the segment to LINE.
 @param Node The node to return from the path.
 */
- (void) removeNodeCheck:(GSNode *) Node ;

- (CGFloat) fitCurveOn1:(NSPoint) On1 off1:(NSPoint*) Off1 Off2:(NSPoint*) Off2 on2:(NSPoint) On2 toPointsQ0:(NSPoint) Q0 q1:(NSPoint)Q1 q2:(NSPoint) Q2 ;

/// Is called from node objects if it has changed.
- (void) elementDidChange:(GSElement*) Element;

/** Returns the count of \a points in the path.

 @return The count of nodes in the path.
 @warnign Deprecated in 1.0.3
 */
- (NSUInteger) count;
/** Returns the count of \a points in the path.
 
 @return The count of nodes in the path.
 */
- (NSUInteger) countOfNodes;
/** Makes the Node the first in the path.

 It checks if the node is in the path. If not, it makes nothing.
 */
- (void) makeNodeFirst: (GSNode*) Node;

/// Closes or opens the Path. If necessary it adds or removes points.
- (void) setClosePath:(BOOL) Closed ;

//// Moves corresponding Offcurve points if Node has been moved.
//- (void) setSmooth_:(GSNode*) Node ;
- (void) setLooked:(GSNode*) Node withPoint:(NSPoint) Point ;
- (void) setSmooth:(GSNode*) Node withCenterPoint:(NSPoint) CenterPoint oppositePoint:(NSPoint) OppositePoint ;
- (void) setSmooth:(GSNode*) Node withCenterNode:(GSNode*) CenterNode oppositeNode:(GSNode*) OppositeNode ;
- (void) setLooked:(GSNode*) Node shadow:(GSNode *) ShadowNode withPoint:(NSPoint) aPoint ;

- (void) checkConnections;
/** Returns the \a point located at \a Index.

 @param Index An index within the bounds of the the \a nodes array.
 @return A GSNode object.
 */
- (GSNode *) nodeAtIndex:(NSInteger)index ;
/** Returns the \a index of the \a Node in the \a path.

 @param Node A GSNode object
 @return The index of the node in the path.
 */
- (NSUInteger) indexOfNode:(GSNode*) Node ;
/// Returns the last node of the path
- (GSNode *) endNode;
/// Returns the first node of the path
- (GSNode *) startNode;
- (GSPathDirection) direction ;
/// Reverses the path direction
- (void) reverse;
/// Returns the undoManager of the parent (GSLayer).
- (NSUndoManager*) undoManager ;
- (GSGlyph *) glyph ; 
- (NSRect) bounds ;
- (void) moveWithPoint:(NSPoint) Point ;
- (CGFloat) tangentAngleAtNode: (GSNode*) Node direction: (int) Direction ;
- (CGFloat) tangentAngleAtNodeAtIndex: (NSInteger) NodeIndex direction: (int) Direction ;
- (NSBezierPath*) bezierPath ;
- (NSArray*) segments ;
- (void) setSegments: (NSArray*) Segments;
- (void) flattenDeltas ;
@end
