//
//  GSFeature.h
//  Glyphs
//
//  Created by Georg Seifert on 9.9.07.
//  Copyright 2007 schriftgestaltung.de. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import <GlyphsCore/GSBase.h>
#import <GlyphsCore/GSContainerProtocol.h>
@class GSSubstitution;
@class GSFont;
@class GSFontMaster;
@class GSInstance;
@class GSFontInfoValue;

NS_ASSUME_NONNULL_BEGIN

NSString *GSRemoveComments(NSString *code);

FOUNDATION_EXPORT NSErrorUserInfoKey FEAErrorSourceErrors;

/** The class defining the feature object

 This class defines the feature object. It is used to store OpenType features in Adobe FDK syntax
 */
@interface GSFeature : NSObject <NSCoding, NSCopying, GSContainerProtocol> {
	GSFont *__weak _parent;
	NSInteger _index;
	NSString *_tag;
	NSString *_code;
	NSMutableArray *_substitutions;
	BOOL _automatic;
	NSString *_notes;
	NSArray *_errors;

#pragma GSAutoCodeStart ivars

	NSMutableArray<GSFontInfoValue *> *_labels;
	BOOL _disabled;

#pragma GSAutoCodeEnd ivars
}

- (instancetype)initWithDict:(NSDictionary *)dict format:(GSFormatVersion)formatVersion;

- (BOOL)isEqualToFeature:(GSFeature *)other;

@property (weak, nonatomic) GSFont *parent;

/** The feature tag.

 e.g: "liga", "smcp", ..
*/
@property (copy, nonatomic) NSString *tag;

- (NSString *)identifier;

/// The feature representation in FDK syntax.
@property (strong, nonatomic, nullable) NSString *code;

@property (nonatomic, readonly, nullable) NSUndoManager *undoManager;

- (NSString *)saveCodeError:(NSError **)error;

- (NSString *)saveNotes;

+ (nullable NSString *)applyTokensToString:(NSString *)code name:(NSString *)name forObjects:(NSArray *)objects langTag:(nullable NSString *)langTag error:(NSError **)error;

+ (nullable NSString *)evaluateToken:(NSString *)token forObjects:(NSArray *)objects error:(NSError **)error;

+ (void)getOperator:(char *)operator token:(NSString *_Nullable *_Nonnull)token otherToken:(NSString *_Nullable *_Nonnull)otherToken font:(GSFont *)font;

+ (NSString *)evaluatePredicateToken:(nonnull NSString *)token font:(nullable GSFont *)font contextLabel:(NSString *)contextLabel error:(NSError **)error;

+ (NSArray <NSString *> *)filterGlyphNamesByPredicateToken:(nonnull NSString *)token font:(nullable GSFont *)font contextLabel:(NSString *)contextLabel error:(NSError **)error;

+ (NSString *)applyVersionNumber:(NSString *)stringValue objects:(NSArray *)objects;

- (BOOL)isStylisticSet;

+ (BOOL)isStylisticSetTag:(NSString *)tag;

- (nullable NSString *)featureNamesString;

- (BOOL)isCharacterVariant;

/** The full, localized name.

 @return The name
 */
- (NSString *)fullName;

/** Returns the content of the object to store it in pList.

 This is used to store the data in the .glyphs file.
 @param format the version of the dict
 */
- (NSDictionary *)propertyListValueFormat:(GSFormatVersion)format;

@property (strong, nonatomic, nullable) NSArray *substitutions;

/** Feature will be automatically generated.

 Defaults to YES, set it to NO if you want to edit the feature manually.
*/
@property (nonatomic) BOOL automatic;

- (void)setAutomaticFast:(BOOL)automatic;

/** Some extra text.

 Is shown in the bottom of the feature window.

 Contains the stylistic set name parameter
 */
@property (copy, nonatomic) NSString *notes;

@property (nonatomic, strong, nullable) NSArray<NSError *> *errors;

@property (nonatomic, assign) NSInteger errorType;

@property (nonatomic, strong, nullable) NSString *errorTooltip;

@property (nonatomic, readonly, nullable) NSImage *errorIcon;

#ifndef GLYPHS_VIEWER

- (BOOL)saveToFile:(FILE *)file format:(GSFormatVersion)formatVersion error:(NSError **)error;

/**
 Invoke this method to regenerate the feature

 If the feature is not set to be automatic, this does nothing
 */
- (void)update;

/// of the featureGenerator can generate the feature
@property (nonatomic, readonly) BOOL canBeAutomated;

///
@property (nonatomic, readonly) BOOL canBeEdited;

/**
 a  dictionary that stores data. It will not be written to disk.
 */
@property (nonatomic, strong, nullable) NSDictionary *tempData;

/**
 Adds key/value to tempData. Pass nil as value to remove previous set data

 @param value and object or nil
 @param key the key
 */
- (void)setTempData:(nullable id)value forKey:(nonnull NSString *)key;

/**
 return value for key in tempData

 @param key the key
 @return a value or nil
 */
- (nullable id)tempDataForKey:(nonnull NSString *)key;

// This is only to be used during export to mark features to that they are not visible in the UI. This is to keep the indexes in the `### feature:X:yyyy ###` in sync
@property (assign) BOOL isVisibleInUI;

#endif

#pragma GSAutoCodeStart methods

#pragma mark Labels

/// The labels.
@property (nonatomic, strong) NSMutableArray<GSFontInfoValue *> *labels;

/** The number of labels */
- (NSUInteger)countOfLabels;

/** Returns object at idx in labels

 @param idx The index
 @return the object at index
 */
- (GSFontInfoValue *)objectInLabelsAtIndex:(NSUInteger)idx;

/** Returns the index of label in labels

 @param label the object
 @return the index of the object
 */
- (NSUInteger)indexOfObjectInLabels:(GSFontInfoValue *)label;

/** Adds the label

 @param label the object to be added
 */
- (void)addLabel:(GSFontInfoValue *)label;

/** Inserts the label at index into labels

 @param label The object to insert
 @param idx The index
 */
- (void)insertObject:(GSFontInfoValue *)label inLabelsAtIndex:(NSUInteger)idx;

/** Removes the label

 @param label the object to be removed
 */
- (void)removeObjectFromLabels:(GSFontInfoValue *)label;

/** Removes the label at idx

 @param idx The index
 */
- (void)removeObjectFromLabelsAtIndex:(NSUInteger)idx;
/**
If the feature is exported or not
 */
@property (nonatomic) BOOL disabled;

#pragma GSAutoCodeEnd methods

@end

NS_ASSUME_NONNULL_END
