//
//  GSFont.h
//  Glyphs
//
//  Created by Georg Seifert on 21.10.05.
//  Copyright 2005 schriftgestaltung.de. All rights reserved.
//

@class GSGlyph;
@class GSLayer;
@class GSDocument;
@class GSFontMaster;
@class GSInstance;
@class GSFeature;
@class GSClass;
@class GSFeaturePrefix;
@class GSFeaBlock;
@class GSCustomParameter;
@class GSGlyphsInfo;

@class GSInfoProperty;
@class GSMetricStore;
#ifndef GLYPHS_VIEWER
@class GSGlyphInfo;
@class GSInfoValueLocalized;
@class GSInfoValue;
#endif
#ifndef GLYPHS_LITE
@class COFont;
@class TTFont;
#endif

#import <GlyphsCore/GSAxis.h>
#import <GlyphsCore/GSBase.h>
#import <GlyphsCore/GSContainerProtocol.h>
#import <GlyphsCore/GSMetric.h>
#import <GlyphsCore/GSColorSpace.h>
#import <GlyphsCore/GSParametersAndPropertiesProtocol.h>
#import <GlyphsCore/GSUserDataProtocol.h>
#import <GlyphsCore/MGOrderedDictionary.h>
#ifdef GLYPHS_VIEWER
#import <GlyphsCore/CFOldStylePList.h>
#endif

NS_ASSUME_NONNULL_BEGIN

/// Localized typographic family names.
extern GSPropertyName const GSPropertyNameFamilyNamesKey;
/// Localized designer names.
extern GSPropertyName const GSPropertyNameDesignersKey;
/// Designer URL.
extern GSPropertyName const GSPropertyNameDesignerURLKey;
/// Localized manufacturer names.
extern GSPropertyName const GSPropertyNameManufacturersKey;
/// Manufacturer URL.
extern GSPropertyName const GSPropertyNameManufacturerURLKey;
/// Localized copyright notices.
extern GSPropertyName const GSPropertyNameCopyrightsKey;
/// Localized OpenType version strings.
extern GSPropertyName const GSPropertyNameVersionStringKey;
/// Combined major and minor font version.
extern GSPropertyName const GSPropertyNameVersionKey;
/// Four-character OpenType vendor identifier.
extern GSPropertyName const GSPropertyNameVendorIDKey;
/// Localized unique font identifiers.
extern GSPropertyName const GSPropertyNameUniqueIDKey;
/// Localized license descriptions.
extern GSPropertyName const GSPropertyNameLicensesKey;
/// License URL.
extern GSPropertyName const GSPropertyNameLicenseURLKey;
/// Localized trademark notices.
extern GSPropertyName const GSPropertyNameTrademarksKey;
/// Localized font descriptions.
extern GSPropertyName const GSPropertyNameDescriptionsKey;
/// Localized sample text.
extern GSPropertyName const GSPropertyNameSampleTextsKey;
/// Legacy nonlocalized PostScript full font name.
extern GSPropertyName const GSPropertyNameFullFontNameKey;
/// Localized PostScript full font names.
extern GSPropertyName const GSPropertyNameFullFontNamesKey;
/// PostScript font name.
extern GSPropertyName const GSPropertyNamePostScriptNameKey;
/// Localized Macintosh-compatible full names.
extern GSPropertyName const GSPropertyNameCompatibleFullNamesKey;
/// Localized typographic subfamily names.
extern GSPropertyName const GSPropertyNameStyleNamesKey;
/// Localized family names used for style mapping.
extern GSPropertyName const GSPropertyNameStyleMapFamilyNamesKey;
/// Localized style names used for style mapping.
extern GSPropertyName const GSPropertyNameStyleMapStyleNamesKey;
/// Localized preferred family names.
extern GSPropertyName const GSPropertyNamePreferredFamilyNamesKey;
/// Localized preferred subfamily names.
extern GSPropertyName const GSPropertyNamePreferredSubfamilyNamesKey;
/// Localized weight, width, and slope family names.
extern GSPropertyName const GSPropertyNameWWSFamilyNameKey;
/// Localized weight, width, and slope subfamily names.
extern GSPropertyName const GSPropertyNameWWSSubfamilyNameKey;
/// Font type classification.
extern GSPropertyName const GSPropertyNameFontTypeKey;
/// Name fragment used to construct an instance name.
extern GSPropertyName const GSPropertyNameInstanceNameParticle;

/// PostScript name of a variable font.
extern GSPropertyName const GSPropertyNameVariablePostScriptNameKey;
/// Localized PostScript name prefixes for variable fonts.
extern GSPropertyName const GSPropertyNameVariablePostScriptNamePrefixKey;
/// Localized style names of a variable font.
extern GSPropertyName const GSPropertyNameVariableStyleNamesKey;

extern NSString *GSFontTypeDefaultKey;
extern NSString *GSFontTypeVariableKey;
extern NSString *GSFontTypeLayerFontKey;
extern NSString *GSFontTypeIconSetKey;

extern NSString *GSFontFilePathKey;

extern UTF32Char FirstUnencoded;
extern UTF32Char LastUnencoded;

extern NSString *GSObjectGroupTypeKey;
extern NSString *GSObjectGroupDisplayNameKey;
extern NSString *GSObjectGroupObjectsKey;

typedef NS_ENUM(int8_t, GSFontType) {
	GSFontTypeDefault = 0,
	GSFontTypeVariable = 1,
	GSFontTypeLayerFont = 2,
	GSFontTypeIconSet = 3,
	GSFontTypeSFSymbol = 4,
};

NSInteger compareKerning(NSString *obj1, NSString *obj2, void *context);
/**
 This class defines the font object.

 Font info properties, that have a user interface, have proper accessors, everything else is stored in the custom parameters
 */
@interface GSFont : NSObject <NSCoding, NSCopying, GSContainerProtocol, GSParametersAndPropertiesProtocol, GSUserDataProtocol> {
	NSMutableArray <GSGlyph *> *_glyphs;
	NSMutableArray <GSInstance *> *_instances;
	GSColorSpace *_colorSpace;
}

#ifndef GLYPHS_VIEWER
/** 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
 */
- (nullable NSDictionary *)propertyListValueFormat:(GSFormatVersion)format error:(out NSError **)error;
#endif

/// unitsPerEm (UPM).
@property (assign, nonatomic) uint32_t unitsPerEm;

#ifdef GLYPHS_LITE
@property (strong, nonatomic, nullable) NSString *license;
#endif

/// versionMajor
@property (assign, nonatomic) NSUInteger versionMajor;

/// versionMinor
@property (assign, nonatomic) NSUInteger versionMinor;

/// The font date
@property (strong, nonatomic) NSDate *date;

@property (nonatomic) BOOL ignoreCompatibilityWarning;

/// The NSColor object of the color label
@property (retain, nonatomic, nullable) NSColor *color;

/** Returns the index of the color label

 @return 0–11, anything else means no label
 */
@property (assign, nonatomic) GSLabelColor colorIndex;

#pragma mark TempData
/**
 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;

#pragma mark -
/** disablesNiceNames

 This is to prevent the automatic glyph name substitution.
 Set it to YES before you do big changes. Make sure to disable it after you are finished.
 */
@property BOOL disablesNiceNames;

/** Disables automatic alignment of components */
@property (nonatomic) BOOL disablesAutomaticAlignment;

/** Keeps alternated glyphs next to the base glyph */
@property (nonatomic) BOOL keepAlternatesTogether;

// key: className, value: DisplayName
@property (nonatomic, strong) NSDictionary <NSString *, NSString *> *dependencies;

- (void)addDependency:(NSString *)className displayName:(NSString *)displayName;

- (void)removeDependency:(NSString *)className;

@property (nonatomic, strong, nullable) NSMutableSet *disabledChangeKeys;

- (void)defaultInit;

#pragma mark -
/// @name Creating and Initializing a GSFont object

/** initializes a font with a dictionary loaded from a pList.

 @param fontDict A dictionary
 @param error If there is a error it contains an NSError object
 */
- (nullable instancetype)initWithDict:(NSDictionary *)fontDict error:(out NSError **)error;

/// @name Creating and Initializing a GSFont object

/** initializes a font with a dictionary loaded from a pList.

 @param fontDict A dictionary
 @param filePath the path of the file, to load linked masters/fonts/image
 @param error If there is a error it contains an NSError object
 */
- (instancetype)initWithDict:(NSDictionary *)fontDict filePath:(nullable NSString *)filePath error:(out NSError **)error;

- (void)readSettingDict:(NSDictionary *)settings;

- (NSDictionary *)writeSettingsDict:(GSFormatVersion)formatVersion;
/**
 Initializes a font with the contents of the location specified by a given URL.

 @param fileURL the location of the file
 @param error If there is a error it contains an NSError object
 @return the GSFont object or nil
 */
- (nullable instancetype)initWithURL:(NSURL *)fileURL error:(out NSError **)error;

- (instancetype)initFast;

/**
 Post processing when read from .glyphs file
 */
- (BOOL)postRead:(out NSError **)error;

- (BOOL)preWrite:(out NSError **)error;

- (void)postProcess;

/// @name Font Methods

#ifndef GLYPHS_VIEWER
#ifndef LIBCORE
#ifndef GLYPHS_LITE

/** Scale the hole font.

 @param scale Multiplier for scale the font (glyphs, kerning and metrics)
 */
- (void)scaleBy:(CGFloat)scale;

#endif
#endif
#endif

- (nullable NSURL *)fileURL;

- (GSFont *)copyWithOptions:(GSGlyphCopyOptions)options;

#pragma mark Font Type

@property (nonatomic) GSFontType fontType;

+ (NSString *)fontTypeKeyForType:(GSFontType)fontType;

+ (GSFontType)fontTypeForTypeKey:(NSString *)fontTypeKey;

#pragma mark Color

/// The RGB color space that is used by the colors of the font.
///
/// This includes color layers, color palettes, and other colors related to the font.
///
/// KVO compliant.
@property (strong, nonatomic, readonly) GSColorSpace *colorSpace;
/// Changes the color space of the font.
///
/// The new color space must follow the RGB color space model.
/// Non-RGB colors are not changed.
///
/// See ``transformColorsUsingBlock:`` for details on which colors are affected.
///
/// This method is also run when the given color space is the same as the color space of the font.
/// This is done so that setting the font’s color space can be used to update stale color values in the font.
- (void)setColorSpace:(GSColorSpace *)colorSpace usingMethod:(GSColorSpaceChangeMethod)changeMethod;
/// Passes each document color to the given block and updates it if the block returns a new color.
///
/// Only colors affecting exported artifacts, like the fill color of a shape on a color layer, are processed by this method.
/// Colors purely for internal use, like a label color of a glyph, are not affected.
///
/// Palette colors (``GSPaletteColor``) are also passed to the block.
/// However, in most cases these do not need to be processed as they reference colors in the color palettes of the font.
/// (The colors of these palettes are passed to the block.)
///
/// Return the original color object to not update a color.
- (void)transformColorsUsingBlock:(NSColor *(^)(NSColor *))block;
/// Returns the given color converted to match the color space of the font.
///
/// Only RGB color are changed to match the font’s color space.
/// Any other color is returned as-is.
- (NSColor *)matchingColorFromColor:(NSColor *)color;

#pragma mark Axes
/// @name Axes

- (nullable GSAxis *)axisForName:(NSString *)axisName;

- (nullable GSAxis *)axisForId:(NSString *)axisId;

- (nullable GSAxis *)axisForTag:(NSString *)axisTag;

#ifndef GLYPHS_LITE
- (NSMutableArray<GSAxis *> *)legacyAxes;

+ (NSArray<GSMetricStore *> *)axesPositionsFromAxes:(NSArray<GSAxis *> *)fontAxes master:(GSFontMaster *)master;

+ (CGFloat *)axesValueListFromAxes:(NSArray<GSAxis *> *)axes axesValues:(GSAxisValues *)axesValues;

/// @return NO if `axes` or `axesValues` are nil or `axes` is empty, YES otherwise.
+ (BOOL)axesValueListFromAxes:(NSArray<GSAxis *> *)axes axesValues:(GSAxisValues *)axesValues intoList:(CGFloat *)axesValueList;

+ (GSMutableAxisValues *)axesValuesFromAxes:(NSArray<GSAxis *> *)axes axesValuesList:(CGFloat *)axesValueList;

// used for compiling feature variations form feature code
- (nullable NSDictionary *)variationAxesRanges:(nullable GSFontMaster *)defaultMaster;

// a list of axes values for each axis
- (NSMutableDictionary *)axesValueSteps:(NSArray *)masterIds glyph:(nullable GSGlyph *)glyph;

- (NSMutableDictionary *)axesValueSteps:(nullable GSGlyph *)glyph;

#endif

- (GSFontMaster *)defaultFontMaster:(nullable GSInstance *)instance;

#ifndef GLYPHS_LITE
- (BOOL)masterRangesInternMin:(CGFloat *)internMin internDefault:(nullable CGFloat *)internDefault internMax:(CGFloat *)internMax externMin:(CGFloat *)externMin externDefault:(nullable CGFloat *)externDefault externMax:(CGFloat *)externMax mastersIntern:(CGFloat *_Nullable *_Nullable)mastersIntern mastersExtern:(CGFloat *_Nullable *_Nullable)mastersExtern defaultMaster:(nullable GSFontMaster *)defaultMaster error:(out NSError **)error;

+ (BOOL)masterRangesFor:(NSArray <GSAxis *>*)axes masters:(NSArray<GSFontMaster *>*)masters customParameters:(NSArray <GSCustomParameter *>*)customParameters internMin:(CGFloat *)internMin internDefault:(nullable CGFloat *)internDefault internMax:(CGFloat *)internMax externMin:(CGFloat *)externMin externDefault:(nullable CGFloat *)externDefault externMax:(CGFloat *)externMax mastersIntern:(CGFloat *_Nullable *_Nullable)mastersIntern mastersExtern:(CGFloat *_Nullable *_Nullable)mastersExtern defaultMaster:(nullable GSFontMaster *)defaultMaster error:(out NSError **)error;

#endif

/// @name Metrics

@property (nullable, strong, nonatomic) NSArray<GSMetric *> *metrics;

@property (nullable, readonly, nonatomic) id metricsContent; // to support KVO;
- (NSUInteger)countOfMetrics;
- (nullable GSMetric *)objectInMetricsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromMetrics:(GSMetric *)metric;
- (void)addMetric:(GSMetric *)metric;

- (nullable GSMetric *)objectInMetricsWithName:(NSString *)name;
- (nullable GSMetric *)objectInMetricsWithType:(GSMetricsType)type withName:(nullable NSString *)name;
- (nullable GSMetric *)objectInMetricsWithType:(GSMetricsType)type withName:(nullable NSString *)name filter:(nullable NSString *)filter;

/// @name Stems

@property (nullable, strong, nonatomic) NSArray<GSMetric *> *stems;
- (NSUInteger)countOfStems;
- (nullable GSMetric *)objectInStemsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromStems:(GSMetric *)stem;
- (void)addStem:(GSMetric *)stem;
- (nullable GSMetric *)stemForId:(NSString *)stemId;
- (nullable GSMetric *)stemForName:(NSString *)name;

/// @name Numbers

@property (nullable, strong, nonatomic) NSArray<GSMetric *> *numbers;
- (NSUInteger)countOfNumbers;
- (nullable GSMetric *)objectInNumbersAtIndex:(NSUInteger)idx;
- (void)removeObjectFromNumbers:(GSMetric *)number;
- (void)addNumber:(GSMetric *)number;
- (nullable GSMetric *)numberForId:(NSString *)name;
- (nullable GSMetric *)numberForName:(NSString *)name;

/// @name Glyphs

/// The array of GSGlyph objects
@property (strong, nonatomic) NSArray<GSGlyph *> *glyphs;

/** allGlyphs
 All glyphs including the imported glyphs.
 */
@property (strong, nonatomic) NSArray<GSGlyph *> *allGlyphs;

- (NSUInteger)count;

/** The count of glyphs in the font */
- (NSUInteger)countOfGlyphs;

/** The glyph object located at index.

 Checks for valid index and returns nil if index is to high.

 @param idx An index within the bounds of the the glyphs array.
 @return a GSGlyph object.
 */
- (nullable GSGlyph *)glyphAtIndex:(NSInteger)idx;

/** Returns the index of the glyph.

 @param glyph The Glyph you are looking for
 @return The index of the glyph or NSNotFound if not found
 */
- (NSInteger)indexOfGlyph:(GSGlyph *)glyph;

@property (nonatomic, readonly) NSDictionary *charsCache;

/** If you changed the glyphs array yourself, call that method to reset some chances. */
- (void)resetCache;

/** Returns the GSGlyph with this name.

 @warning This is a bit slow.

 @param name the name of the glyph.
 @return a GSGlyph object.
 */
- (nullable GSGlyph *)glyphForName:(NSString *)name;

- (nullable GSGlyph *)localGlyphForName:(NSString *)name;

#ifndef GLYPHS_LITE
/**
 A list of glyph names matching query

 @param query This can be a name containing wildcards ("a.*") or a query ("script=arabic")
 @param error if something goes wrong, it contains an error on return
 @return a list of glyph names or nil
 */
- (nullable NSArray *)glyphNamesForWildcard:(NSString *)query contextLabel:(NSString *)contextLabel error:(out NSError **)error;

- (nullable NSSet *)expandWildcardsInNameList:(NSArray *)nameList contextLabel:(NSString *)contextLabel error:(out NSError **)error;

#ifndef LIBCORE
- (nullable NSString *)baseName:(NSString *)name forWildCard:(NSString *)wild;
#endif

- (void)prepareName2Glyph;
#endif

- (GSGlyph *)glyphForNameFast:(NSString *)name;

/** A list of glyph names

 @return A list of glyph names
 */
- (NSArray *)glyphNames;

- (NSArray *)exportingGlyphNames;

/** Returns the GSGlyph with this this Unicode.

 @param unicode the unicode as a hex string ('004C')
 @return a GSGlyph object or nil if not found.
 @see resetCache If you changed some glyphs and this method returns wrong results, call resetCache
 */
- (nullable GSGlyph *)glyphForUnicode:(NSString *)unicode;

- (nullable GSGlyph *)glyphForUnicodeFast:(NSString *)unicode;

/** Returns the GSGlyph with this this Unicode.

 @param unicodes a list of unicodes as hex strings ('004C')
 @return a GSGlyph object or nil if not found.
 @see resetCache If you changed some glyphs and this method returns wrong results, call resetCache
 */
- (nullable GSGlyph *)glyphForUnicodes:(NSOrderedSet *)unicodes;
- (nullable GSGlyph *)localGlyphForUnicodes:(NSOrderedSet *)unicodes;

- (nullable GSGlyph *)localGlyphForUnicodeFast:(NSString *)unicode;

- (void)glyphHasChangedName:(GSGlyph *)glyph oldName:(nullable NSString *)oldName;

#ifndef GLYPHS_VIEWER
- (GSGlyph *)newGlyphWithName:(NSString *)glyphName;

/** Adds a new glyph with this glyphName to the font

 @param glyphName  The new glyph name
 @param changeName If changeName is yes, the glyphName will be converted to nice-name, otherwise not.

 @return The new glyph.
 */
- (GSGlyph *)newGlyphWithName:(NSString *)glyphName changeName:(BOOL)changeName;

- (void)makeSafeGlyphInfo:(GSGlyph *)glyph;
- (void)makeSaveGlyphInfo:(GSGlyph *)glyph GSDeprecated("makeSafeGlyphInfo:");

- (void)calculateDefaultWidth:(GSGlyph *)glyph;

/** Calculates a names that is unique for the font

 @param glyph The Glyph

 @return The glyph name with a .0XX suffix if the name is already in use by another glyph
 */
- (NSString *)safeNameForGlyph:(GSGlyph *)glyph;
- (NSString *)saveNameForGlyph:(GSGlyph *)glyph GSDeprecated("safeNameForGlyph:");

- (nullable NSString *)safeSuffixForGlyph:(GSGlyph *)glyph;
- (nullable NSString *)saveSuffixForGlyph:(GSGlyph *)glyph GSDeprecated("safeSuffixForGlyph:");
/** Calculates a names that is unique for the font

 @param glyphName The glyph name

 @return The glyph name with a .0XX suffix if the name is already in use by another glyph
 */
- (NSString *)safeNameForName:(NSString *)glyphName;
- (NSString *)saveNameForName:(NSString *)glyphName GSDeprecated("safeNameForName:");

#endif

/** Returns the GSGlyph with this ID.

 @warning This is a bit slow.

 @param ID the ID of the glyph.
 @return a GSGlyph object.
 */
- (nullable GSGlyph *)glyphForId:(NSString *)ID;

/**
 Checks whether the receiver contains a glyph with the specified name.
 */
- (BOOL)hasGlyphWithName:(NSString *)glyphName;
/** Returns all glyphs for the names.

 @param glyphNames a list a names
 @return a list of glyphs or nil
 */
- (nullable NSArray<GSGlyph*> *)glyphsForNames:(NSArray <NSString*> *)glyphNames;

#ifndef GLYPHS_VIEWER
/** Tests if all the glyphs are present and set to export

 @param glyphNames A array of glyph names
 @return YES if all glyphs will end up in an exported font.
 @see filterKeepGlyphs:
 @see filterGlyphs:
 */
- (BOOL)keepsGlyphs:(NSArray<NSString *> *)glyphNames;

/** Tests if all the glyphs are present and set to export

 @param unicodes A array of unicodes
 @return YES if all glyphs will end up in an exported font.
 @see filterKeepGlyphs:
 @see filterGlyphs:
 */
- (BOOL)keepsGlyphsCode:(NSArray<NSString *> *)unicodes;
#endif
/** Returns all glyph names that are present and set to export

 @param glyphNames A array of glyph names
 @return A list of exporting glyphs
 @see keepsGlyphs:
 @see filterGlyphs:
 */
- (nullable NSArray *)filterKeepGlyphs:(NSArray<NSString *> *)glyphNames;

- (nullable NSArray *)filterKeepGlyphsCodes:(NSArray<NSString *> *)unicodes;
/** Returns all glyph names that are present and set to export

 @param glyphNames A array of glyph names
 @return A list of all glyphs that are in the font
 @see keepsGlyphs:
 @see filterKeepGlyphs:
 */
- (nullable NSArray <NSString *> *)filterGlyphs:(NSArray<NSString *> *)glyphNames;
#ifndef GLYPHS_VIEWER
- (NSUInteger)countOfGlyphsWithInfosByName:(NSArray<GSGlyphInfo *> *)glyphInfos;

- (NSUInteger)countOfGlyphsWithCode:(NSArray<NSNumber *> *)codes;

- (NSArray *)glyphsContainingComponentWithName:(NSString *)glyphName masterId:(NSString *)masterID;
#endif

/** Returns the glyph with the chars unicode.

 @param aChar A (unicode) char.
 @return a GSGlyph object
 @see characterForGlyph:
 */
- (nullable GSGlyph *)glyphForCharacter:(UTF32Char)aChar;

- (nullable GSGlyph *)glyphFromCharsCacheForUnicode:(NSString *)unicode;

- (nullable GSGlyph *)glyphFromCharsCacheForChar:(UTF32Char)aChar;
/// Faster as it assumes that the glyphs are read-access locked and does not run `preloadCharCache`.
- (nullable GSGlyph *)glyphFromCharsCacheForCharFast:(UTF32Char)aChar;

- (void)preloadCharCache;

/** Returns a UTF32Char for the glyph.

 It uses the unicode to find the char value. For unencoded glyphs it returns a cached PUA value.

 @param glyph a GSGlyph object
 @return a UTF32Char
 @sa glyphForCharacter:
 */
- (UTF32Char)characterForGlyph:(GSGlyph *)glyph;

#ifndef GLYPHS_VIEWER

- (NSSet *)componentGlyphNamesForGlyph:(GSGlyph *)glyph;

/** Adds the Glyph object to the font.

 @param glyph A GSGlyph object.
 */
- (void)addGlyph:(GSGlyph *)glyph;

- (void)addGlyphFast:(GSGlyph *)glyph;

/** Adds the Glyphs object to the font.

 @param glyphs A NSArray of GSGlyph objects.
 */
- (void)addGlyphsFromArray:(NSArray<GSGlyph *> *)glyphs;

/** Removes the Glyph from the font

 @param glyph A GSGlyph to remove from the font.
 */
- (void)removeGlyph:(GSGlyph *)glyph;

/** Removes the Glyphs from the font

 @param glyphs A NSArray of GSGlyph to remove from the font.
 */
- (void)removeGlyphs:(NSArray<GSGlyph *> *)glyphs;

#endif

#ifndef LIBCORE
/** Is called if the there are changes. */
- (void)sortGlyphs;
#endif

- (void)sortGlyphs:(NSMutableArray *)glyphs withList:(nullable NSArray *)nameList;

/** Triggers the sorting of kerning */
- (void)sortKerning;

/// Sort Metrics with values from first master
- (void)sortMetrics;

- (void)elementDidChange:(nullable id)element;

// needed for control cached interpolation stuff. lastChange is reset on undo so it can’t cover this.
@property (atomic) NSTimeInterval lastKerningChange;

/** The panose value for the font */
- (nullable NSMutableArray *)panose;

#pragma mark masters

/// @name Masters

/// An array of GSFontMaster objects
@property (strong, nonatomic) NSArray<GSFontMaster *> *fontMasters;

@property (strong, nonatomic) NSArray<GSFontMaster *> *importedFontMasters;

@property (strong, nonatomic) NSArray<GSFont *> *importedFonts;

@property (strong, nonatomic) NSArray<GSGlyph *> *importedGlyphs;
/** The count of masters in the font.

 @return The number of layers currently in the font.
 */
- (NSInteger)countOfFontMasters;

/** The master located at index

 @param idx An index
 @return A GSFontMaster instance or nil if index is out of bounds
 */
- (nullable GSFontMaster *)fontMasterAtIndex:(NSInteger)idx;

- (NSUInteger)indexOfFontMaster:(GSFontMaster *)master;
/** Returns the fontMaster with this id

 @param id The ID of the font master. This is supposed to be a Unique id
 @return A GSFontMaster instance.
 */
- (nullable GSFontMaster *)fontMasterForId:(nullable NSString *)id;

/** Returns the fontMaster with this name

 @param name The name of the font master.
 @return A GSFontMaster instance.
 */
- (nullable GSFontMaster *)fontMasterForName:(NSString *)name;

- (NSString *)newMasterId;

#ifndef GLYPHS_LITE
#ifndef GLYPHS_VIEWER
/** Inserts the FontMaster at idx

 @param fontMaster The master to add to the font
 @param idx The index to insert FontMaster.
 */
- (void)insertFontMaster:(GSFontMaster *)fontMaster atIndex:(NSUInteger)idx;

/** Adds the fontMaster to the font

 @param fontMaster The master to add.
 */
- (void)addFontMaster:(GSFontMaster *)fontMaster;
#endif
#endif
/** Removes the fontMaster from the font

 @param fontMaster The master to remove.
 */
- (void)removeFontMaster:(GSFontMaster *)fontMaster;

#ifndef GLYPHS_LITE
- (GSFontMaster *)addFontMasterAndContent:(GSFontMaster *)fontMaster;

- (GSFontMaster *)insertFontMasterAndContent:(GSFontMaster *)fontMaster atIndex:(NSUInteger)index;

- (void)removeFontMasterAndContent:(GSFontMaster *)fontMaster;

- (void)replaceFontMasterAtIndex:(NSUInteger)idx withFontMaster:(GSFontMaster *)fontMaster;

- (void)copyGlyphs:(nonnull GSFont *)sourceFont sourceFontMasterID:(nonnull NSString *)sourceFontMasterID targetFontMasterID:(nonnull NSString *)targetFontMasterID addMissing:(BOOL)addMissing;

- (void)copyInfoFrom:(GSFont *)sourceFont sourceFontMasterID:(NSString *)sourceFontMasterID targetFontMasterID:(NSString *)targetFontMasterID;

- (void)copyLayersFrom:(GSFont *)otherFont sourceFontMasterID:(NSString *)sourceFontMasterID targetFontMasterID:(NSString *)targetFontMasterID;

#ifndef GLYPHS_VIEWER
- (GSFontMaster *)addFontAsNewMaster:(GSFontMaster *)master;

- (BOOL)addMasterFromInstance:(GSInstance *)instance error:(NSError **)error;

#endif

#pragma mark imported Masters

@property (readonly) NSArray <GSFontMaster *> *allMasters;

- (NSUInteger)countOfAllMasters;

- (nullable GSFontMaster *)allMasterAtIndex:(NSInteger)idx;

- (NSUInteger)indexOfObjectInAllMasters:(GSFontMaster *)master;

- (nullable GSFontMaster *)masterNearestToPosition:(CGFloat *)position;

- (nullable GSFontMaster *)masterNearestToPosition:(CGFloat *)position glyph:(nullable GSGlyph *)glyph;

- (nullable GSFontMaster *)masterAtPosition:(CGFloat *)position;

- (nullable GSInstance *)instanceAtPosition:(CGFloat *)position;

- (nullable GSInstance *)instanceNearestToPosition:(CGFloat *)position distance:(nullable CGFloat *)distance;

- (BOOL)reloadLinkedFonts:(out NSError **)error;
#endif

#pragma mark metrics
#ifndef GLYPHS_VIEWER
/**
 Recalculate the LSB and RSB for all glyph

 This will not apply the metrics keys.
 */
- (void)updateMetrics;

#endif
#pragma mark instances

/// @name Instances

/// An array of GSInstance objects. This define export settings for interpolation and naming.
@property (strong, nonatomic) NSArray<GSInstance *> *instances;

/** The count of the Instances

 @return The number of Instances currently in the Font.
 */
- (NSUInteger)countOfInstances;

/** The Instance at index

 @param idx The index of the instance.
 @return The Instance located at _index_.
 */
- (nullable GSInstance *)objectInInstancesAtIndex:(NSUInteger)idx;

#ifndef GLYPHS_VIEWER

/** Inserts the instance at Index

 @param instance The instance to insert.
 @param idx The _index_ at what to insert the _instance_.
 */
- (void)insertObject:(GSInstance *)instance inInstancesAtIndex:(NSUInteger)idx;
- (void)insertInstance:(GSInstance *)instance atIndex:(NSUInteger)idx;

/** Adds the Instance to the font

 @param instance The Instance to add to the font.
 */
- (void)addInstance:(GSInstance *)instance;

- (void)addInstanceFast:(GSInstance *)instance;

#endif

#ifndef GLYPHS_LITE
#ifndef GLYPHS_VIEWER
- (void)removeInstance:(GSInstance *)instance;

- (void)removeInstances:(NSArray *)instances;
/** Removes the Instance at Index.

 @param idx The of the Instance to be removed.
 */
- (void)removeObjectFromInstancesAtIndex:(NSUInteger)idx;

- (void)replaceObjectInInstancesAtIndex:(NSUInteger)idx withObject:(GSInstance *)instance;

- (NSArray *)instanceGroups;
#endif

/**
 this returns a lists of instance with unique instances only for glyph.layerGroups
 */
- (NSArray *)instancesUnique;

#pragma mark kerning

/**
 The master that will supply the tt/ps hints

 @param master the master that should get the hints
 */
- (nonnull NSString *)masterIDforHints:(nullable GSFontMaster *)master;
#endif
/// @name Kerning

- (MGOrderedDictionary *)kerningForDirection:(GSWritingDirection)direction;

#ifndef GLYPHS_LITE
- (NSString *)masterIDforMetrics:(NSString *)masterID;

- (NSString *)masterIDforMetrics:(NSString *)masterID hasLink:(nullable BOOL *)hasLink;
#endif

- (MGOrderedDictionary *)masterKerning:(NSString *)masterID direction:(GSWritingDirection)direction;

/** the Kerning of the Font

 1) A Dict for each FontMaster (FontMaster id as key)
 2) The Dict contains an entry for each glyph (the glyphID or GroupName (@MMK_L_XXX) is used as key)
 3) These entries hold the values: glyphID or GroupName (@MMK_R_XXX) as key, kerning as value.
 */
@property (strong, nonatomic) MGOrderedDictionary<NSString *, MGOrderedDictionary *> *kerningLTR;
@property (strong, nonatomic) MGOrderedDictionary<NSString *, MGOrderedDictionary *> *kerningRTL;
@property (strong, nonatomic) MGOrderedDictionary<NSString *, MGOrderedDictionary *> *kerningContext;

/** the vertical Kerning of the Font

 1) A Dict for each FontMaster (FontMaster id as key)
 2) The Dict contains an entry for each glyph (the glyphID or GroupName (@MMK_L_XXX) is used as key)
 3) These entries hold the values: glyphID or GroupName (@MMK_R_XXX) as key, kerning as value.
 */
@property (strong, nonatomic) MGOrderedDictionary<NSString *, MGOrderedDictionary *> *kerningVertical;

#ifndef GLYPHS_VIEWER

/** Compresses the kerning

 if a GSGlyph has a Kerning Group and Direct Kerning, the Kerning is changed to Class Kerning.
 */
- (void)compressKerningForDirection:(GSWritingDirection)direction;

- (void)cleanUpKerningForDirection:(GSWritingDirection)direction;

- (void)migrateRTLKerning;

- (nullable MGOrderedDictionary<NSString *, MGOrderedDictionary *> *)migrateRTLKerningDict:(NSMutableDictionary *)kerningDict doClasses:(BOOL)doClasses;

- (nullable MGOrderedDictionary *)backportRTLKerning;

- (void)replaceKey:(NSString *)newKey forMasterIds:(NSArray *)masterIds leftKey:(NSString *)leftKey rightKey:(NSString *)rightKey side:(NSString *)side writingDirection:(GSWritingDirection)writingDirection;
#endif

- (void)setKerning:(MGOrderedDictionary *)kerning forMaster:(NSString *)fontMasterID direction:(GSWritingDirection)direction;

- (void)addKerning:(MGOrderedDictionary *)kerning forMaster:(NSString *)fontMasterID direction:(GSWritingDirection)direction;

- (CGFloat)kerningForFontMasterID:(NSString *)fontMasterID firstGlyph:(GSGlyph *)firstGlyph secondGlyph:(GSGlyph *)secondGlyph direction:(GSWritingDirection)direction;

- (CGFloat)kerningForFontMasterDict:(NSDictionary *)masterKerning firstGlyph:(GSGlyph *)firstGlyph secondGlyph:(GSGlyph *)secondGlyph direction:(GSWritingDirection)direction;

/** Returns a kerning value

 @param fontMasterID The Master id
 @param leftKey either a glyph id or a glyph group (@MM_L_XXX)
 @param rightKey either a glyph id or a glyph group (@MM_R_XXX)
 @return the kerning value, or NSNotFound if there is no pair
 */

- (CGFloat)kerningForFontMasterID:(id)fontMasterID leftKey:(id)leftKey rightKey:(id)rightKey direction:(GSWritingDirection)direction;

#ifndef GLYPHS_VIEWER
/** adds a kerning value

 @param fontMasterID The Master id
 @param leftKey either a glyph id or a glyph group (@MM_L_XXX)
 @param rightKey either a glyph id or a glyph group (@MM_R_XXX)
 @param value the kerning value
 */

- (void)setKerningForFontMasterID:(id)fontMasterID leftKey:(id)leftKey rightKey:(id)rightKey value:(CGFloat)value direction:(GSWritingDirection)direction;

/** removes a kerning value

 @param fontMasterID The Master id
 @param leftKey either a glyph id or a glyph group (@MM_L_XXX)
 @param rightKey either a glyph id or a glyph group (@MM_R_XXX)
 */

- (void)removeKerningForFontMasterID:(NSString *)fontMasterID leftKey:(NSString *)leftKey rightKey:(NSString *)rightKey direction:(GSWritingDirection)direction;

- (CGFloat)contextKerningForKey:(id)key fontMasterID:(id)masterID;

- (void)setContextKerningForKey:(id)key fontMasterID:(id)masterID value:(CGFloat)value;

- (void)replaceContextKerningKey:(NSString *)key key:(NSString *)replaceKey;

- (void)removeContextKerningForKey:(id)key fontMasterID:(id)masterID;

+ (NSArray *)parseContextKey:(NSString *)str;

#endif

#pragma mark features

/// @name Features

/// An array of GSFeature objects.
@property (strong, nonatomic) NSArray<GSFeature *> *features;

#ifndef GLYPHS_VIEWER
/** The count of the features

 @return The number of features in the Font.
 */
- (NSUInteger)countOfFeatures;

/** Returns the index of feature in features

 @param feature the object
 @return the index of the object
*/
- (NSUInteger)indexOfFeature:(GSFeature *)feature;

/** The feature at index

 @param idx The index of the feature
 @return The feature located at idx.
 */
- (nullable GSFeature *)objectInFeaturesAtIndex:(NSUInteger)idx;

/// Inserts the Feature at idx
- (void)insertObject:(GSFeature *)feature inFeaturesAtIndex:(NSUInteger)idx;

/// Removes the Feature at idx
- (void)removeObjectFromFeaturesAtIndex:(NSUInteger)idx;

- (void)replaceObjectInFeaturesAtIndex:(NSUInteger)idx withObject:(GSFeature *)feature;

//- (void)replaceFeaturesAtIndexes:(NSIndexSet *)indexes withFeatures:(NSArray *)featureArray;

/// Adds the Feature
- (void)addFeature:(GSFeature *)feature;

- (void)removeFeature:(GSFeature *)feature;

/** Returns the feature with the name or tag.

 @param tag The feature tag (like "smcp")
 */
- (nullable GSFeature *)featureForTag:(NSString *)tag;

#ifndef GLYPHS_LITE

- (nullable GSFeature *)automaticFeatureForTag:(NSString *)tag hasAnyFeature:(BOOL *)hasAnyFeature;

- (nullable GSFeature *)automaticFeatureForTag:(NSString *)tag;

- (nullable GSFeature *)activeFeatureForTag:(NSString *)tag;

- (BOOL)updateFeatures:(NSError **)error;

- (BOOL)importFeatures:(NSString *)featuresString error:(out NSError **)error;

#endif
#endif
#pragma mark Classes

/// @name Classes

/// An array of GSClasse objects
@property (strong, nonatomic) NSArray<GSClass *> *classes;

#ifndef GLYPHS_VIEWER
- (NSMutableArray<GSClass *> *)mutableClasses;

/// The count of the classes
- (NSUInteger)countOfClasses;

- (nullable GSClass *)objectInClassesAtIndex:(NSUInteger)index;

- (NSUInteger)indexOfObjectInClasses:(GSClass *)aClass;

/** Returns the class with the name.

 @param tag The class name.
 */
- (nullable GSClass *)classForTag:(NSString *)tag;

/** Adds a class to the font

 @param aClass the Class
 */
- (void)addClass:(GSClass *)aClass;

/** Insert the Class at idx in the font

 @param aClass the class
 @param idx the index
 */
- (void)insertObject:(GSClass *)aClass inClassesAtIndex:(NSUInteger)idx;

/** Remove the class at idx from the font

 @param idx the index
 */
- (void)removeObjectFromClassesAtIndex:(NSUInteger)idx;

/** Removes the class from the font

 @param aClass the class
 */
- (void)removeClass:(GSClass *)aClass;

/** Replaces the the class a idx with Class

 @param idx the index
 @param aClass the class
 */
- (void)replaceObjectInClassesAtIndex:(NSUInteger)idx withObject:(GSClass *)aClass;

/** Convenient method to add a class with the Text

 @param text the class in FDK syntax, e.g. "@myClass = [A B];"
 */
- (void)addClassFromCode:(NSString *)text;
#endif
#pragma mark FeaturePrefixes

/// @name FeaturePrefixes

/**
 An array of GSFeaturePrefix objects that contain additional lookups
 */
@property (nonatomic, strong) NSArray<GSFeaturePrefix *> *featurePrefixes;

#ifndef GLYPHS_VIEWER
/** Adds the Prefix to the font

 @param thePrefix the prefix
 */
- (void)addFeaturePrefix:(GSFeaturePrefix *)thePrefix;

/** the count of the Prefixes in the font */
- (NSUInteger)countOfFeaturePrefixes;

- (nullable GSFeaturePrefix *)objectInFeaturePrefixesAtIndex:(NSUInteger)idx;

/** Returns the Prefix with the name.

 @param tag The prefix name.
 */
- (nullable GSFeaturePrefix *)featurePrefixForTag:(NSString *)tag;

/** Insert the Prefix at idx in the font

 @param thePrefix the prefix
 @param idx the idx
 */
- (void)insertObject:(GSFeaturePrefix *)thePrefix inFeaturePrefixesAtIndex:(NSUInteger)idx;

/** Remove the Prefix at idx from the font

 @param thePrefix the prefix
 */
- (void)removeFeaturePrefix:(GSClass *)thePrefix;

/// Returns the FEA block (feature, class, prefix) matching the given file name.
///
/// Returns `nil`, if no block was saved or imported using a matching file name.
- (nullable GSFeaBlock *)feaBlockForFileName:(NSString *)fileName;

/// Adds a feature block to the font, basing the type and title on the file name.
///
/// When an existing block with no code matches the file name, it is used instead (its code is set, it is returned) and no new block is added to the font.
///
/// > Note: This is a low-level API, reserved for uses that deal with the inner workings of a Glyphs package.
/// Consider using the high-level APIs such as `-addFeature:`, `-addClass:`, `-addFeaturePrefix:` instead.
- (nullable GSFeaBlock *)addFeaBlockForFileName:(NSString *)fileName code:(NSString *)code;

#pragma mark display
/** Converts a string that contains slash separated glyph names in a regular unicode string

 @param string A String containing slash separated glyph names
 @return A UTF-16 string. For for unencoded glyphs, it will assign cached PUA codes
 */
- (NSString *)charStringFromDisplayString:(NSString *)string;

/** Delays redrawing and updates.

 Will record the changes and update once in `enableUpdateInterface`. If you don’t need updates, use `stopUpdateInterface`

 @see stopUpdateInterface
 @warning Always call enableUpdateInterface afterwards
 */
- (void)disableUpdateInterface;

/** Disable redrawing and updates completely.

 Changes will not trigger an update. Only use this carefully and call enableUpdateInterface if you need future updates.

 @see disableUpdateInterface
 @warning Always call enableUpdateInterface afterwards
 */
- (void)stopUpdateInterface;

/** Reenables redrawing and updates.

 This only has an effect if disableUpdateInterface was called before
 */
- (void)enableUpdateInterface;

- (void)enableFutureUpdates;
/** Check if the updating is enabled

 @return NO if disableUpdateInterface was called
 */
- (BOOL)isUpdateInterfaceEnabled;

#endif

- (nullable GSGlyphsInfo *)glyphsInfo;

#pragma mark Metrics

/** The size of the grid.

 If it is `0`, all values are stored as floats. `1` and above will ALWAYS round the coordinates.

 @see gridLength
 */
@property (nonatomic, assign) uint32_t gridMain;

/** The subdivision of the grid.

 Divides the grid.

 @see gridLength
 */
@property (nonatomic, assign) uint32_t gridSubDivision;

@property (assign) uint32_t gridMainStore;

@property (assign) uint32_t gridSubDivisionStore;

/** The effective grid width.

 Calculated by Grid / Subdivision

 @return The effective size of the grid
 */
- (CGFloat)gridLength;

@property (nonatomic, assign) CGFloat keyboardIncrement;

@property (nonatomic, assign) CGFloat keyboardIncrementBig;

@property (nonatomic, assign) CGFloat keyboardIncrementHuge;

@property (nonatomic, assign) BOOL previewRemoveOverlap;

@property (nonatomic, assign) BOOL snapToObjects;

- (BOOL)importAFM:(NSString *)AFMString fontMaster:(nullable GSFontMaster *)fontMaster verticalMetrics:(BOOL)verticalMetrics metrics:(BOOL)doMetrics kerning:(BOOL)doKerning error:(out NSError **)error;

@property (nonatomic, strong) NSArray *displayStrings;
@property (nonatomic, strong) NSString *appVersion;
@property (nonatomic, strong) NSString *storedFileType;
@property (nonatomic) GSFormatVersion formatVersion;
@property (nonatomic) GSFormatVersion storedFormatVersion;

#ifndef GLYPHS_VIEWER
/**
 Adds a new font info value to the array specified by `key` or updates an existing one.

 @param name The key whose plural form specifies an array property of `GSInfoValue` objects on the receiver.
 @param value The actual value to be added. Or nil to remove an existing value
 @param languageTag The language under which the value should be stored. Defaults to `English` if nil is passed.
 */
- (void)setProperty:(GSPropertyName)name value:(nullable NSString *)value languageTag:(nullable NSString *)languageTag;

- (nullable GSInfoProperty *)propertyForName:(GSPropertyName)name;

- (nullable GSInfoValue *)propertyForName:(GSPropertyName)name languageTag:(NSString *)languageTag;

- (nullable NSString *)defaultPropertyForName:(nonnull GSPropertyName)name;

- (void)setDefaultProperty:(GSPropertyName)name value:(id)value;

+ (NSArray *)allowedPropertyKeys;

+ (NSArray *)legacyInfoKeys;

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

- (void)disableUndo;
- (void)enableUndo;

#endif

/**
 @note The receiver’s implementation of `undoManager` returns the parent’s undo manager. It is only used for font info and for adding/removing glyphs. Each glyph has its own undo manager (see `-[GSGlyph undoManager]`).
 */
@property (nullable, nonatomic, weak) GSDocument *parent;

- (void)invalidateCustomParameterCache;

#ifndef GLYPHS_VIEWER
/**
 Tags in all glyphs.
 */
@property (nullable, nonatomic, readonly) NSArray<NSString *> *allTags;

- (nonnull NSString *)nameUI;

- (GSInfoValueLocalized *)preferredFamilyNames:(out NSError **)error;
#endif

- (void)setReadBuffer:(NSObject *)values forKey:(NSString *)key;

#pragma mark - Start auto interface

- (void)lockReadGlyphs;

- (void)unlockReadGlyphs;

- (void)lockWriteGlyphs;

- (void)unlockWriteGlyphs;

#pragma GSAutoCodeStart methods

#ifndef GLYPHS_VIEWER
/// The fontName.
@property (nonatomic, strong) NSString *fontName;
#endif

#pragma mark Axes

/// The axes.
@property (nonatomic, strong, null_resettable) NSMutableArray<GSAxis *> *axes;

/// Returns a filtered view of `axes` containing only the canonical axes of the font.
///
/// See the ``GSAxis/isCanonical`` docs for details.
@property (nonatomic, readonly) NSArray<GSAxis *> *canonicalAxes;

/** The number of axes */
- (NSUInteger)countOfAxes;

/** Returns object at idx in axes

 @param idx The index
 @return the object at index
 */
- (nullable GSAxis *)objectInAxesAtIndex:(NSUInteger)idx;

/** Returns the index of axis in axes

 @param axis the object
 @return the index of the object
 */
- (NSUInteger)indexOfObjectInAxes:(GSAxis *)axis;

/** Adds the axis

 @param axis the object to be added
 */
- (void)addAxis:(GSAxis *)axis;

/** Inserts the axis at index into axes

 @param axis The object to insert
 @param idx The index
 */
- (void)insertObject:(GSAxis *)axis inAxesAtIndex:(NSUInteger)idx;

/** Removes the axis

 @param axis the object to be removed
 */
- (void)removeObjectFromAxes:(GSAxis *)axis;

/** Removes the axis at idx

 @param idx The index
 */
- (void)removeObjectFromAxesAtIndex:(NSUInteger)idx;

#pragma mark Properties

/// The properties.
@property (nonatomic, strong, null_resettable) NSMutableArray<GSInfoProperty *> *properties;

/** The number of properties */
- (NSUInteger)countOfProperties;

/** Returns object at idx in properties

 @param idx The index
 @return the object at index
 */
- (nullable GSInfoProperty *)objectInPropertiesAtIndex:(NSUInteger)idx;

/** Returns the index of property in properties

 @param property the object
 @return the index of the object
 */
- (NSUInteger)indexOfObjectInProperties:(GSInfoProperty *)property;

/** Adds the property

 @param property the object to be added
 */
- (void)addProperty:(GSInfoProperty *)property;

- (void)addPropertyFast:(GSInfoProperty *)property;

/** Inserts the property at index into properties

 @param property The object to insert
 @param idx The index
 */
- (void)insertObject:(GSInfoProperty *)property inPropertiesAtIndex:(NSUInteger)idx;

#ifndef GLYPHS_VIEWER
/** Removes the property

 @param property the object to be removed
 */
- (void)removeObjectFromProperties:(GSInfoProperty *)property;

/** Removes the property at idx

 @param idx The index
 */
- (void)removeObjectFromPropertiesAtIndex:(NSUInteger)idx;
#endif

#pragma mark Custom Parameter

/// @name customParameters

/**
 The customParameters.
 A list of customParameters objects
 */
@property (nonatomic, strong, null_resettable) NSMutableArray<GSCustomParameter *> *customParameters;

/** The count of customParameters */
- (NSUInteger)countOfCustomParameters;

- (nullable GSCustomParameter *)objectInCustomParametersAtIndex:(NSUInteger)idx;

- (BOOL)customBoolValueForKey:(NSString *)key;

- (nullable id)customColorValueForKey:(NSString *)key;

/// The value of the customParameters where name == Key
- (nullable id)customValueForKey:(NSString *)key;

/// The customParameters where name == Key
- (nullable GSCustomParameter *)customParameterForKey:(NSString *)key;

- (nullable GSCustomParameter *)customParameterActiveForKey:(NSString *)key;

#ifndef GLYPHS_VIEWER
/** Set the value for key

 It will look for an existing parameter with the name an overwrite its value, or adds a new parameter
 @param value The value to add
 @param key   The name of the parameter
 */
- (void)setCustomValue:(nullable id)value forKey:(NSString *)key;

- (void)addCustomParameter:(GSCustomParameter *)property;

- (void)removeObjectFromCustomParameters:(GSCustomParameter *)customParameter;

/** Removes the first parameter with then Name

 @param key The name
 */
- (void)removeObjectFromCustomParametersForKey:(NSString *)key;

- (void)insertObject:(GSCustomParameter *)customParameter inCustomParametersAtIndex:(NSUInteger)idx;

- (void)removeObjectFromCustomParametersAtIndex:(NSUInteger)idx;

- (void)replaceObjectInCustomParametersAtIndex:(NSUInteger)idx withObject:(GSCustomParameter *)customParameter;
#endif

/// The note.
@property (nonatomic, strong, nullable) NSString *note;

#pragma mark User Data

/// @name UserData
/** Place to store data.

 Here it is possible to store something. Please use a unique key.
 The objects should be able to serialize to a plist. If they are not, they should return all infos to store in description (as String).
 */
@property (strong, nonatomic, nullable) NSDictionary *userData;

/**
 convenience accessor to get to the content of the userData dict

 @param key the key
 @return the data stored with key
 */
- (nullable NSObject *)userDataForKey:(NSString *)key;

/** Adds something to the fonts userData.

 This also triggers undo/document dirty state.

 @param value The object should be able to serialize to a plist. If they are not, they should return all infos to store in description (as String).
 @param key   Please use an unique key that gives some indication who put it there (e.g. prefix it with your name or project).
 */
- (void)setUserData:(nullable id)value forKey:(nonnull NSString *)key;

/** Removed the object with this key.

 @param key The key to remove
 */
- (void)removeUserDataForKey:(NSString *)key;
#pragma GSAutoCodeEnd methods
@end

NS_ASSUME_NONNULL_END
