//
//  GSFeaBlock.h
//  GlyphsCore
//
//  Created by Florian Pircher on 28.06.24.
//  Copyright © 2024 schriftgestaltung.de. All rights reserved.
//

#import <GlyphsCore/GSBase.h>

NS_ASSUME_NONNULL_BEGIN

@class GSFont;
@class GSSaveContext;

typedef NS_ENUM(uint8_t, GSFeaBlockType) {
	GSFeaBlockTypePrefix,
	GSFeaBlockTypeClass,
	GSFeaBlockTypeFeature,
};

/// A snippet of feature code.
@interface GSFeaBlock : NSObject <NSCoding, NSCopying> {
	GSFont *__weak _parent;
	NSString *_code;
	BOOL _automatic;
	BOOL _disabled;
	NSString *_notes;
	NSArray *_errors;
	BOOL _isVisibleInUI;
	NSString *_identifier;
}

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

// 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;

/// A reference to the font containing the block.
@property (weak, nonatomic) GSFont *parent;

/// A persistent, per-font unique identifier of the block.
@property (strong, readonly) NSString *identifier;

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

/// A way to access tag/name regardless of the feature/class
@property (strong, nonatomic, nullable) NSString *nameUI;

- (NSString *)saveCode;

/// Sets the code, skipping the undo system.
- (void)setCodeFast:(NSString *)code;

/// Whether the code can be generated automatically.
@property (nonatomic, readonly) BOOL canBeAutomated;

/// Whether the code is generated automatically.
@property (nonatomic, getter=isAutomatic) BOOL automatic;

- (void)setAutomaticFast:(BOOL)automatic;

/// If the block is automatic, updates the code. Otherwise, does nothing.
- (void)update;

/// Whether the block is included in the exported font.
@property (nonatomic, getter=isDisabled) BOOL disabled;

@property (nonatomic, readonly) BOOL canBeEdited;

- (BOOL)validateName:(id _Nonnull *_Nonnull)ioValue error:(NSError **)error;

/// Additional notes about the block that are not part of the code.
@property (strong, nonatomic) NSString *notes;

- (NSString *)saveNotes;

/// A time interval that is incremented whenever the title or code of the block is updated.
@property (atomic) NSTimeInterval lastOperationInterval;

/// The file name stem (file name without extension) that best matches the block.
///
/// The preferred name might not be usable when naming conflicts arise.
/// Such conflicts are resolved outside this property.
@property (readonly, nonatomic) NSString *preferredFileNameStem;
/// A file path relative to the `features` directory in a Glyphs Package file.
///
/// Unset when the block does not correspond to a file.
/// Before saving the document, this value is updated to match the new file path in case a change is required.
/// A change might be required when there are multiple features with the same name.
/// In that case, the first block might be written as `calt.fea` and the second as `calt.2.fea`.
@property (strong, nullable) NSString *filePath;

/// Extracts the title and type of a block from its file name.
///
/// For features, the title is the tag, for classes and prefixes, the title is the name.
///
/// - Parameter fileName: The file name of the block.
/// - Parameter blockType: Set to the type of the block, if non-`NULL`.
/// - Returns: The title of the block, or `nil`, if the file name is not valid for a block.
+ (nullable NSString *)blockTitleFromFileName:(NSString *)fileName blockType:(nullable GSFeaBlockType *)blockType;

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

@property (nonatomic, assign) NSInteger errorType;

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

@property (nonatomic, readonly, nullable) NSImage *errorIcon;
/// A dictionary that stores data that is not 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;
/**
 Returns a value for the given  key in tempData.

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

/** Returns the content of the block 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 error:(out NSError **)error;

#ifndef GLYPHS_VIEWER

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

#endif

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

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

@end

NS_ASSUME_NONNULL_END
