//
//  GSGlyphViewProtocol.h
//  GlyphsCore
//
//  Created by Georg Seifert on 26.01.10.
//  Copyright 2010 schriftgestaltung.de. All rights reserved.
//

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

typedef NS_ENUM(uint8_t, GSKerningMode) {
	GSKerningNormal = 1,
	GSKerningContextual = 2
};

@class GSLayer;
@class GSTextStorage;
@class GSLayoutManager;

NS_ASSUME_NONNULL_BEGIN

/** This protocol defines the API for the graphicView */
@protocol GSGlyphEditViewProtocol

/** The active layer

 If only one layer is selected it retunes it, otherwise it retunes nil.

 In the editview, this is the layer that has a gray info box.
 */
@property (nonatomic, nullable, strong) GSLayer *activeLayer;

/** The position of the activeLayer

 This is in scaled view coordinates.

 @see scale
 */
@property (nonatomic) NSPoint activePosition;

- (NSAffineTransform *)zoomTransformForPosition:(NSPoint)position doOffset:(BOOL)offset;

- (void)bezierPathToViewSpace:(NSBezierPath *)bezierPath atPoint:(NSPoint)layerOrigin doOffset:(BOOL)offset;

- (void)bezierPathToViewSpace:(NSBezierPath *)bezierPath atPoint:(NSPoint)layerOrigin;

/// The scale of the view
@property (nonatomic) CGFloat scale;

/// The index of the character of the active layer in the string
@property (nonatomic) NSUInteger activeIndex;

/** number of layers in the view.

 This might be difference than the number of characters in the string after the features are applied
 */
@property (nonatomic, readonly) NSUInteger cachedLayerCount;

/// the selection range in characters as in the original string
@property (nonatomic) NSRange selectedRange;

/**
 The layer selection range after features have been applied.

 @note This should now return the contents of the new `selectedLayerRange` property.
 */
@property (nonatomic, readonly) NSRange cachedLayerSelectionRange;

/**
 The layer selection range after features have been applied.

 When setting this property, the `selectedRange` property should also be set to the corresponding converted character range.
 When setting the `selectedRange` property (except in the case above), this property should be set to {NSNotFound, 0}.
 When getting this property, the actual ivar should only be returned if it is not {NSNotFound, 0}. Otherwise, the corresponding converted character range should be returned.

 @note Setting this property should implicitly set `selectionAnchorLayerIndex` if its length is 0.
 */
@property (nonatomic) NSRange selectedLayerRange;

/**
 Marks the starting point of selection.

 @note This property should be set implicitly when `selectedLayerRange` is set and its length is 0.
 */
@property (nonatomic) NSUInteger selectionAnchorLayerIndex;

- (UTF32Char)charAtIndex:(NSUInteger)index;

/// the currently active cursor
@property (nonatomic, retain, nullable) NSCursor *cursor;

@property (nonatomic) NSRect glyphFrame;

@property (nonatomic) NSRect userVisibleRect;

@property (nonatomic, readonly) NSRect saveVisibleRect;
/** the text storage */
@property (strong, nonatomic, nonnull) GSTextStorage *textStorage;

@property (nonatomic) GSKerningMode kerningMode;

/// Set if kerning is active
@property (nonatomic, assign) BOOL doKerning;

/// Set if spacing is active
@property (nonatomic, assign) BOOL doSpacing;

/// The layout manager
@property (strong, nonatomic, nonnull) GSLayoutManager *layoutManager;

@property (readonly, nonatomic, nullable) NSColor *canvasColor;
@property (readonly, nonatomic, nullable) NSColor *backgroundStrokeColor;
@property (readonly, nonatomic, nullable) NSColor *backgroundStrokeColorDark;
@property (readonly, nonatomic, nullable) NSColor *otherLayersStrokeColor;
@property (readonly, nonatomic, nullable) NSColor *otherLayersStrokeColorDark;
@property (readonly, nonatomic, nullable) NSColor *foregroundColor;
@property (nonatomic) BOOL drawDark;
///

- (NSPoint)getLocation:(nullable NSEvent *)theEvent;

/** Translates the view coordinate from the event into glyph coordinates of the active layer

 @param theEvent a mouse down even

 @return The coordinates
 */
- (NSPoint)getActiveLocation:(nullable NSEvent *)theEvent;

/** Returns the cached layer at index

 @param index The cached index

 @return The layer
 */
- (nullable GSLayer *)cachedGlyphAtIndex:(NSUInteger)index;

/** Returns the cached position at a layer index

 @param index The cached index

 @return the position
 */
- (NSPoint)cachedPositionAtIndex:(NSUInteger)index;

/**
 Should pass the given graphical position to `-layerIndexForPoint:` and convert the layer index to a character index.

 @note This may not be the desired index if a character is comprised of multiple glyphs. Instead, use `-layerIndexForPoint:` directly and set the `selectedLayerRange` property.

 @param point The graphical position to check, in view coordinates.

 @return The index of the character whose bounding box contains the point.
 */
- (NSUInteger)characterIndexForPoint:(NSPoint)point;

/**
 Converts the given graphical position to a layer index.

 @param point The graphical position to check, in view coordinates.

 @return The index of the layer whose bounding box contains the point.
 */
- (NSUInteger)layerIndexForPoint:(NSPoint)point;

- (void)drawLayer:(nonnull GSLayer *)layer atPoint:(NSPoint)layerOrigin asActive:(BOOL)active attributes:(nullable NSDictionary *)attributes;

- (void)reflow;

- (void)replaceCharactersInRange:(NSRange)aRange withString:(nonnull NSString *)string;

@end

NS_ASSUME_NONNULL_END
