//
//  GSGlyphsInfo.h
//  Glyphs
//
//  Created by Georg Seifert on 20.1.08.
//  Copyright 2008 schriftgestaltung.de. All rights reserved.
//

#import <Cocoa/Cocoa.h>

#import <GlyphsCore/GSGlyph.h>

#ifndef LIBCORE
#import <GlyphsCore/GSSidebarItem.h>
#endif

@class GSGlyphInfo;
@class GSFont;
@class GSLayer;
@class MGOrderedDictionary;
@class GSSidebarItem;

/** \brief GSGlyphsInfos: This is a singleton class to provide glyphinfo services.
 \ingroup common
 This is a singleton class to provide glyphinfo services.
 */
@interface GSGlyphsInfo : NSObject {

	NSMutableArray *_glyphInfos;
	NSMutableArray *_categories;
	NSMutableArray *_subCategories;
	NSMutableArray *_sidebarCategories;
	NSDictionary *_categoryIndexes;
	NSDictionary *_sidebarSubcategories;
	NSMutableDictionary<NSString *, GSSidebarItem *> *_name2Group;
	NSMutableDictionary *_name2Info;
	NSMutableArray *_allNiceNames;
	NSMutableDictionary *_unicode2Info;
	NSMutableArray *_scriptIDs;
	NSDictionary *_scriptIndexes;
	NSDictionary *_anchors;
	NSDictionary *_defaultMetrics;

	NSURL *_localURL;
	NSURL *_localInfoURL;
	NSDictionary *_iMatraCombinations;

  @private
	BOOL _isGlobal;
	NSOperationQueue *_queue;

	GSSidebarItem *_allItem;
	GSSidebarItem *_categoriesGroup;
	GSSidebarItem *_languagesGroup;
	NSArray *_filterGroups;
}
/** An array of glyph groups.

This is used the build the filter tree in font view mode.
*/
@property (readonly, nonatomic) NSMutableArray *sidebarCategories;
@property (readonly, nonatomic) GSSidebarItem *languagesGroup;
/// The array containing the glyphs info data.
@property (strong, nonatomic) NSMutableArray *glyphInfos;
@property (readonly, nonatomic) NSMutableArray *scriptIDs;
@property (nonatomic, readonly) NSArray *categories;
@property (nonatomic, readonly) NSArray *subCategories;
@property (nonatomic, readonly) NSDictionary *defaultMetrics;
@property (readonly, nonatomic, class) NSDictionary *customParameterTypes;
@property (readonly, nonatomic, class) NSDictionary *customParameterMapping2to3;
@property (readonly, nonatomic, class) NSDictionary *customParameterMapping3to2;

@property (readonly, nonatomic, class) NSArray *customFontParameters;
@property (readonly, nonatomic, class) NSArray *customMasterParameters;
@property (readonly, nonatomic, class) NSArray *customInstanceParameters;
@property (readonly, nonatomic, class) NSArray *customVariableInstanceParameters;

@property (readonly, nonatomic, class) NSDictionary *basicFontInfoProperties;
/// The width classes
@property (readonly, nonatomic, class) NSDictionary *widthName2Classes;
@property (readonly, nonatomic, class) NSDictionary *widthClass2Names;
/// The weight classes
@property (readonly, nonatomic, class) NSDictionary *weightName2Classes;
@property (readonly, nonatomic, class) NSDictionary *weightClass2Names;

/// The width classes
@property (readonly, nonatomic, class) NSDictionary *localizedWidthName2Classes;
@property (readonly, nonatomic, class) NSDictionary *localizedWidthClass2Names;
/// The weight classes
@property (readonly, nonatomic, class) NSDictionary *localizedWeightName2Classes;
@property (readonly, nonatomic, class) NSDictionary *localizedWeightClass2Names;

@property (readonly, nonatomic) NSDictionary *name2Info;
@property (readonly, nonatomic) NSArray *allNiceNames;
@property (readonly, nonatomic) NSDictionary *unicode2Info;
//@property (readonly, nonatomic) NSDictionary *scriptRanges;
@property (readonly, nonatomic) NSSet *indicScripts;
@property (readonly, nonatomic) NSDictionary *iMatraCombinations;

/// Returns the shared GlyphsInfos object.
+ (GSGlyphsInfo *)sharedManager;

- (instancetype)initWithLocalFile:(NSURL *)localURL;

+ (NSDateFormatter *)dateFormat;

+ (NSString *)applicationSupportFolder;

+ (NSString *)applicationSupportPath;

+ (NSArray *)applicationSupportPaths;

/** Returns the GSGlyphInfo for the glyph with Glyph.

@param glyph The glyph.
@return A GSGlyphInfo instance or nil.
*/
- (GSGlyphInfo *)glyphInfoForGlyph:(GSGlyph *)glyph;

/** Returns the GSGlyphInfo for the glyph with Name.

@param name The glyph name.
@return A GSGlyphInfo instance or nil.
*/
- (GSGlyphInfo *)glyphInfoForName:(NSString *)name;

/** Returns the GSGlyphInfo for the glyph with Unicode.

@param unicode A unicode as Hex string.
@return A GSGlyphInfo instance or nil.
*/
- (GSGlyphInfo *)glyphInfoForUnicode:(NSString *)unicode;
- (GSGlyphInfo *)glyphInfoForUnicodes:(NSOrderedSet *)unicodes;

/// Returns the index of the glyph in the database.
- (NSUInteger)glyphIndex:(GSGlyph *)glyph;

+ (BOOL)isPrivateUse:(UTF32Char)aChar;

+ (BOOL)isRTLScript:(NSString *)script;

+ (BOOL)isCJKScript:(NSString *)script;

+ (BOOL)isValidIdentifier:(NSString *)identifier;

+ (BOOL)isKeepNameCategory:(NSString *)category;

/** Returns the name of the lowercase glyph name linked to the given uppercase name

 in most instances this is equivalent with `[name lowercaseString]` but there are some exceptions. e.g. A > a, KoppaArchaic > koppaArchaic
 @param name a upper case glyph name
 @return the matching lower case name
 */
- (NSString *)lowerCaseName:(NSString *)name;

- (NSString *)doubleUnicodeForGlyph:(GSGlyph *)glyph;
/**
 Updates the glyph info in the Glyph.

 @param glyph      The Glyph
 @param changeName Keep the name and only update unicode, categories and script
 */
- (void)updateGlyphInfo:(GSGlyph *)glyph changeName:(BOOL)changeName;

- (void)updateGlyphInfo:(GSGlyph *)glyph changeName:(BOOL)changeName changeUnicode:(BOOL)changeUnicode;

#ifndef GLYPHS_VIEWER
#ifndef LIBCORE
///

/** Generates missing anchors in the Layer.

 @param layer The Layer

 @return YES if it changed anything.
 */
- (BOOL)updateAnchor:(GSLayer *)layer;
#endif
#endif

/** Converts a name to a standardised name

 e.g. converts afii10017 to A-cy

 @param name The name.
 @return The nice-name.

 @see productionGlyphNameForName:
*/
- (NSString *)niceGlyphNameForName:(NSString *)name;

/** Converts a name to a production name

 @param name The name.
 @return The production name.
 @see niceGlyphNameForName:
 */
- (NSString *)productionGlyphNameForName:(NSString *)name;

- (NSString *)productionGlyphNameForGlyph:(GSGlyph *)glyph;


/**
 Converts a string into a list of glyph names

 This can be a space/comma/newline/tab separated list of names
 or
 a string of none ASCII codes (e.g. ideographs)

 @param string a string of glyph names or characters
 @returns a list of glyph names
 */
- (NSArray *)glyphNamesFromString:(NSString *)string;

/** Converts all glyph names to production names

 This is useful for OT-feature code

 @param string A string that contains glyph names like feature code.
 @return The string with converted names.
 */
- (NSString *)convertToLegacyNames:(NSString *)string font:(GSFont *)font;

+ (NSString *)convertNames:(NSDictionary *)changeNames inString:(NSString *)featuresString;

- (void)fixASCIINames:(GSFont *)font;

- (NSString *)decomposeHangul:(unichar)s;

+ (BOOL)decomposeHangul:(unichar)s leadingConsonant:(unichar *)leadingConsonant vowel:(unichar *)vowel trailingConsonant:(unichar *)trailingConsonant;

+ (unichar)composeHangulLeadingConsonant:(unichar)leadingConsonant vowel:(unichar)vowel trailingConsonant:(unichar)trailingConsonant;

- (short)hangulComponentPositionForName:(NSString *)name;

- (short)hangulComponentPositionForUnichar:(unichar)aChar;

- (NSArray *)hangulJamoGlyphsForPos:(short)pos;

+ (NSString *)hangulPositionKeyForName:(NSString *)name;

+ (NSArray *)hangulFirstConsonants;
+ (NSArray *)hangulVowels;
+ (NSArray *)hangulFinalConsonants;

+ (NSString *)CIDShortResourceName:(GSFont *)font;

+ (NSString *)CIDFullResourceName:(GSFont *)font;

- (NSArray *)completionsForName:(NSString *)partialName forPartialWordRange:(NSRange)charRange;

- (NSUInteger)indexOfObjectInScripts:(NSString *)script;

- (NSUInteger)indexOfObjectInCategories:(NSString *)category;

- (NSMutableDictionary *)_subcategoriesForSidebarCategory:(NSString *)category;

+ (GSScriptTag)scriptTagForScriptID:(GSScriptID)script;

+ (NSString *)scriptNameForScriptTag:(GSScriptTag)script;

+ (NSDictionary *)script2Tag;

+ (GSScriptID)scriptIDForScriptTag:(GSScriptTag)scriptTag;

+ (NSDictionary *)scriptSuffixes;

+ (NSDictionary *)languageScripts;

+ (NSSet *)scriptTags;

+ (NSSet *)indicScripts;

+ (NSArray *)languageData;

+ (NSNumber *)macEncodingIDForTag:(NSString *)language;
+ (NSNumber *)macLanguageIDForTag:(NSString *)language;
+ (NSNumber *)winLanguageIDForName:(NSString *)language; // this shouldn’t be needed
+ (NSNumber *)winLanguageIDForTag:(NSString *)language;

+ (NSString *)langTagForName:(NSString *)name;
+ (NSString *)langNameForTag:(NSString *)tag;

+ (NSString *)winTagForLanguageID:(NSInteger)languageID;

+ (NSString *)winNameForLanguageID:(NSInteger)languageID;

+ (NSString *)languageNameForLanguageID:(NSInteger)languageID platformID:(NSInteger)platformID;

+ (NSString *)languageTagForLanguageID:(NSInteger)languageID platformID:(NSInteger)platformID;

+ (int)propertyName2NameId:(NSString *)propertyName;

+ (NSString *)nameId2PropertyName:(int)nameId;

+ (NSArray *)unicodeRanges;

+ (NSArray *)codePageRanges;

+ (NSString *)closestWeightClass:(int)weightClass;

- (NSString *)ligaNameForComponents:(NSArray<NSString *> *)componentNames;

- (NSArray *)componentsForLigaName:(NSString *)ligaName font:(GSFont *)font;

+ (NSString *)langSuffixForName:(NSString *)name;

+ (NSArray *)blueValues:(NSArray *)alignmentZones;

+ (NSArray *)otherBlues:(NSArray *)alignmentZones;

+ (NSString *)glyphNameToFileName:(NSString *)glyphName;

+ (BOOL)isASCIIString:(NSString *)string;

+ (NSArray<NSColor *> *)labelColors;

+ (NSArray<NSNumber *> *)variationSelectors;

/**
 StandardizedVariants.txt
 keys are glyph names for the first column, values is a list of (VS, name)
 */
+ (NSDictionary *)defaultVariationSelectors;

+ (BOOL)validateDefaultName:(NSString *)value key:(NSString *)key minLength:(NSUInteger)minLength maxLength:(NSUInteger)maxLength error:(NSError **)error;

+ (BOOL)validatePostScriptName:(id *)ioValue error:(NSError **)error;

/**
 Removes all illegal parts from the file name and masks reserved file name parts
 */
+ (NSString *)validFileName:(NSString *)fileName;

+ (NSCharacterSet *)illegalFileNameCharacters;

+ (NSCharacterSet *)illegalPostScriptNameCharacters;

+ (NSCharacterSet *)illegalNameCharacters;

+ (void)registerPlaceholderFont:(NSString *)fontPath forScript:(NSString *)script;

+ (void)removePlaceholderFontForScript:(NSString *)script;

+ (NSFont *)fontForScript:(NSString *)script size:(CGFloat)size;

@end

@interface GSGlyph (ApplyGlyphInfo)

- (void)applyGlyphInfo:(GSGlyphInfo *)info changeName:(BOOL)changeName changeUnicode:(BOOL)changeUnicode;

- (void)applyGlyphInfoFast:(GSGlyphInfo *)info changeName:(BOOL)changeName changeUnicode:(BOOL)changeUnicode;
@end
