//
//  GSContainerProtocol.h
//  GlyphsCore
//
//  Created by Georg Seifert on 22.02.14.
//  Copyright (c) 2014 schriftgestaltung.de. All rights reserved.
//

#import <GlyphsCore/GSBase.h>

#ifdef GLYPHS_VIEWER
#define GS_SET_ELEMENT_PROPERTY_INT(OLD, NEW, LABEL)
#define GS_SET_ELEMENT_PROPERTY_FLOAT(OLD, NEW, LABEL)
#define GS_SET_ELEMENT_PROPERTY_POINT(OLD, NEW, LABEL)
#define GS_SET_ELEMENT_PROPERTY_OBJECT(OLD, NEW, LABEL)
#define GS_SET_ELEMENT_PROPERTY_CHILD(OLD, NEW, LABEL)
#else
#define GS_SET_ELEMENT_PROPERTY(OLD, NEW, LABEL, COMP) if (COMP) { \
	GS_PUSH_UNDO(NEW, LABEL); \
	OLD = NEW; \
	[_parent elementDidChange:self]; \
}
#define GS_SET_ELEMENT_PROPERTY_CHILD(OLD, NEW, LABEL) if (![OLD isEqual:NEW]) { \
	GS_PUSH_UNDO(NEW, LABEL); \
	OLD = NEW; \
	OLD.parent = self; \
	[_parent elementDidChange:self]; \
}
#define GS_SET_ELEMENT_PROPERTY_INT(OLD, NEW, LABEL) \
	GS_SET_ELEMENT_PROPERTY(OLD, NEW, LABEL, (OLD != NEW))
#define GS_SET_ELEMENT_PROPERTY_FLOAT(OLD, NEW, LABEL) \
	GS_SET_ELEMENT_PROPERTY(OLD, NEW, LABEL, (fabs(OLD - NEW) > 0.001))
#define GS_SET_ELEMENT_PROPERTY_POINT(OLD, NEW, LABEL) \
	GS_SET_ELEMENT_PROPERTY(OLD, NEW, LABEL, (fabs(OLD.x - NEW.x) > 0.001 || fabs(OLD.y - NEW.y) > 0.001))
#define GS_SET_ELEMENT_PROPERTY_OBJECT(OLD, NEW, LABEL) \
	GS_SET_ELEMENT_PROPERTY(OLD, NEW, LABEL, (![OLD isEqual:NEW]))
#endif

@class GSFont;
@class GSGlyph;
@class GSLayer;
@class GSSaveContext;

NS_ASSUME_NONNULL_BEGIN

@protocol GSContainerProtocol <NSObject>

@optional

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

@property (nonatomic, readonly, nullable) GSFont *font;
@property (nonatomic, readonly, nullable) GSGlyph *glyph;
@property (nonatomic, readonly, nullable) GSLayer *layer;

#ifndef GLYPHS_VIEWER
@property (nonatomic, readonly, nullable) NSUndoManager *undoManager;
@property (nonatomic, readonly, nullable) NSUndoManager *undoManagerCheck;
#endif

@end

typedef NSObject<GSContainerProtocol> GSContainer;

@protocol GSItemProtocol <NSObject>

/// init from property list
- (instancetype)initWithDict:(NSDictionary *)dict format:(GSFormatVersion)formatVersion;

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

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

#if DEBUG
@property (unsafe_unretained, nonatomic, nullable) GSContainer *parent;
#else
@property (weak, nonatomic, nullable) GSContainer *parent;
#endif

#ifndef GLYPHS_VIEWER
@property (nonatomic, readonly, nullable) NSUndoManager *undoManager;
#endif

@optional

// Post processing when read from .glyphs file
- (void)postRead:(GSFormatVersion)formatVersion;

+ (BOOL)singleValue;

@end

NS_ASSUME_NONNULL_END
