//
//  GSLayoutManager.h
//  FunTextField
//
//  Created by Yung-Luen Lan on 6/24/08.
//  Copyright 2008 yllan.org. All rights reserved.
//

#import <GlyphsCore/GlyphsCore.h>

extern NSString *GSMarkedTextAttributeName;

@class GSGlyphEditView;
@class GSCFIndexToCFIndexMap;

#if TARGET_OS_IOS
@interface GSTextPosition : UITextPosition

@property (assign) NSInteger position;

@end
#endif

@interface GSLayoutManager : NSObject

@property (unsafe_unretained, nonatomic) GSGlyphEditView *containerView;
@property (assign, nonatomic) NSSize cachedSize;

@property (readonly, nonatomic) NSArray <GSLayer *> *cachedLayers;

// The layers used for drawing. can be interpolated Layers
@property (readonly, nonatomic) NSArray <GSLayer *> *cachedDrawLayers;

@property (readonly, nonatomic) NSPoint *cachedLayersPosition;
@property (copy, nonatomic) NSAttributedString *cachedAttributedString;
@property (copy, nonatomic) NSDictionary *cachedActiveAttributes;
@property (nonatomic) CGFloat lineHeight;
@property (strong, nonatomic) NSArray *cachedFeatures;

/// ----------------------------------------------------------------------------
/// @name Layouting Glyphs
/// ----------------------------------------------------------------------------

/// Performs a simplified implementation of the *Unicode Standard Annex #9 – Unicode Bidirectional Algorithm* based on the `direction` of the glyphs of the layers.
///
/// Returns `GSWritingDirectionBIDI` if there is no inherent writing direction.
///
/// > Note: The same can be accomplished on a string using `-[NSString inherentWritingDirection]`.
+ (GSWritingDirection)inherentWritingDirectionOfLayers:(NSArray<GSLayer *> *)layers;

/* Create the geometry of attributed string and cache the information */
- (void)layoutString:(NSAttributedString *)string;

/// ----------------------------------------------------------------------------
/// @name Managing the Active Layer
/// ----------------------------------------------------------------------------

- (void)updateActiveLayer;

/// ----------------------------------------------------------------------------
/// @name Calculating Rectangles for Character Ranges
/// ----------------------------------------------------------------------------

/* Return a rectangle near the first character in range of string */
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange;

- (NSPoint)cachedDrawLayersPositionAtIndex:(NSUInteger)idx;

/// ----------------------------------------------------------------------------
/// @name Calculating Indexes for Graphical Points
/// ----------------------------------------------------------------------------

- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint;

- (NSUInteger)layerIndexForPoint:(NSPoint)thePoint;

/// Like ``layerIndexForPoint:``, but prefers a layer whose drawn outline contains the point (searching outward from the
/// active layer), falling back to the layer-box hit test when no outline is hit. Used for double-click glyph selection.
- (NSUInteger)layerIndexForGlyphSelectionAtPoint:(NSPoint)thePoint;

/// ----------------------------------------------------------------------------
/// @name Converting between Character and Layer (Glyph) Positions
/// ----------------------------------------------------------------------------

/// This property should normally not be modified directly. It is exposed mainly for state restoration purposes.
@property (nonatomic, strong) GSCFIndexToCFIndexMap *characterIndexesByLayerIndex;

/// This property should normally not be modified directly. It is exposed mainly for state restoration purposes.
@property (nonatomic, strong) GSCFIndexToCFIndexMap *replacedCharacterIndexesByLayerIndex;

- (NSUInteger)characterIndexForLayerIndex:(NSUInteger)layerIndex;

- (NSUInteger)layerIndexForCharacterIndex:(NSUInteger)characterIndex;

- (NSRange)characterRangeForLayerRange:(NSRange)layerRange;

- (NSRange)layerRangeForCharacterRange:(NSRange)characterRange;

/// ----------------------------------------------------------------------------
/// @name Drawing Text
/// ----------------------------------------------------------------------------

- (void)updateCachedLayerPaths;

- (void)drawTextWithSelectedLayerRange:(NSRange)layerRange
								inRect:(NSRect)dirtyRect;

/* Destroy the cached geometry information. */
- (void)endDrawText;

#ifndef GLYPHS_LITE
- (void)respondToCallback:(id)handler hash:(NSString *)hash operation:(NSString *)operation exception:(NSException *)exception;
#endif

@end
