//
//  GSGlyph+Interpolation.h
//  GlyphsCore
//
//  Created by Georg Seifert on 01.06.22.
//  Copyright © 2022 schriftgestaltung.de. All rights reserved.
//

#import <GlyphsCore/GSGlyph.h>

@class VarLibModel;

NS_ASSUME_NONNULL_BEGIN

@interface GSGlyph (Interpolation)

/// A detached layer formed by applying interpolation coefficients to compatible source layers.
///
/// The coefficients are keyed by layer or font master identifier.
/// A coefficient can be scalar or contain independent horizontal and vertical values.
/// The source layers must have matching structure.
///
/// - Parameter interpolation: The interpolation coefficient for each participating layer or font master identifier.
/// - Parameter masters: The font masters corresponding to the source layers.
/// - Parameter error: On return, an error that prevented complete interpolation.
- (nullable GSLayer *)interpolate:(nonnull NSDictionary *)interpolation
						  masters:(nonnull NSArray *)masters
							error:(NSError **)error;

/// A detached layer interpolated for an instance, or `nil` when interpolation fails.
///
/// This method accounts for active Intermediate and Alternative layers, Smart Components, and pre-interpolation filters.
/// The source layers must have matching structure.
///
/// - Parameter instance: The instance that supplies the interpolation location and settings.
/// - Parameter masters: The font masters participating in the interpolation.
/// - Parameter scale: The coordinate scale applied to the result.
/// - Parameter keepSmart: Whether Smart Components remain components when possible.
/// - Parameter smartSettings: Smart Component settings applied before interpolation, or `nil` for no override.
/// - Parameter layerName: The name of corresponding source layers to interpolate, or `nil` for the primary layers.
/// - Parameter additionalLayers: A collection to which interpolated color and corner layers are appended, or `nil` when they are not needed.
/// - Parameter error: On return, an error that prevented interpolation.
- (nullable GSLayer *)interpolateFull:(nullable GSInstance *)instance
							  masters:(NSArray *)masters
								scale:(CGFloat)scale
							keepSmart:(BOOL)keepSmart
						smartSettings:(nullable NSDictionary *)smartSettings
							layerName:(nullable NSString *)layerName
					 additionalLayers:(nullable NSMutableArray *)additionalLayers
								error:(NSError *_Nullable *)error NS_REFINED_FOR_SWIFT;

/// Adds the corresponding interpolated Smart Component layers to a target glyph.
///
/// This method has no effect when the glyph has no glyph-local axes.
///
/// - Parameter baseLayer: The primary interpolated layer whose Smart Component coordinates are completed.
/// - Parameter instance: The instance that supplies the interpolation location.
/// - Parameter scale: The coordinate scale applied to the added layers.
/// - Parameter targetGlyph: The glyph that receives the added layers.
- (void)interpolateSmartLayer:(GSLayer *)baseLayer
					 instance:(GSInstance *)instance
						scale:(CGFloat)scale
				  targetGlyph:(GSGlyph *)targetGlyph;

/// Replaces layer contents with interpolation from the remaining layers in each layer group.
///
/// Use this to recalculate Intermediate layers or restore font master layers from the other masters.
///
/// - Parameter layers: The layers belonging to the glyph that are recalculated.
/// - Parameter error: On return, an error that prevented recalculation.
/// - Returns: Whether all requested layers were recalculated.
- (BOOL)replaceLayersWithInterpolation:(NSArray<GSLayer *> *)layers
								 error:(NSError **)error;

/// Decomposes components requiring layer-specific interpolation across each layer group.
///
/// This includes components with a keep-weight setting or component master identifier.
/// Smart Components with piece settings are also decomposed unless they are retained explicitly.
/// Layers in a group must use compatible shape ordering.
/// Corresponding shape indexes are decomposed throughout each layer group to preserve interpolation compatibility.
/// Component anchors are materialized, and automatic alignment is disabled for remaining components.
///
/// - Parameter keepSmart: Whether Smart Components with piece settings remain components when no other condition requires decomposition.
/// - Returns: Whether any layer group contained a component requiring decomposition.
- (BOOL)decomposeSpecialComponents:(BOOL)keepSmart NS_SWIFT_NAME(decomposeSpecialComponents(keepingSmartComponents:));

/// Finds the nearest font master in one direction along an axis while keeping the other axis coordinates fixed.
///
/// - Parameter layerAxisLocation: A buffer containing one internal coordinate for each font axis, in font axis order.
/// - Parameter masterPos: On return, the coordinate of the matching font master on the selected axis when a match is found.
/// - Parameter axisIdx: The index of the axis along which to search.
/// - Parameter direction: A nonzero value whose sign selects greater or smaller coordinates.
/// - Returns: The matching font master identifier, or `nil` when no font master exists in that direction.
- (nullable NSString *)nextLayerId:(CGFloat *)layerAxisLocation layerPos:(CGFloat *)masterPos onAxis:(NSInteger)axisIdx direction:(int)direction NS_REFINED_FOR_SWIFT;

#pragma mark - Deprecated (Glyphs 3 compatibility)

- (void)replaceLayersWithInterpolation:(NSArray<GSLayer *> *)layers GSDeprecated("replaceLayersWithInterpolation:error:");

@end

#ifndef GLYPHS_VIEWER
@interface GSFont (Interpolation)

/// locations as needed to make an VarLibModel
+ (nullable NSArray *)locationsForAxes:(nonnull NSArray <GSAxis *>*)axes
							   masters:(NSArray <GSFontMaster *>*)masters
								 glyph:(nullable GSGlyph *)glyph;

+ (nullable NSArray <NSDictionary <OTAxisTag, NSNumber *> *> *)normalizedLocationsForFont:(nonnull GSFont *)font
																			defaultMaster:(GSFontMaster *)defaultMaster
																				  masters:(NSArray<GSFontMaster *> *)masters
																					error:(NSError **)error;

+ (nullable NSArray <NSDictionary <OTAxisTag, NSNumber *> *> *)normalizedLocationsForFont:(nonnull GSFont *)font
																			defaultMaster:(GSFontMaster *)defaultMaster
																				masterIds:(NSArray<NSString *> *)masterIds
																					glyph:(nullable GSGlyph *)glyph
																					error:(NSError **)error;

@end
#endif
NS_ASSUME_NONNULL_END
