/*
 * This file is part of the ZYJSDWebImage package.
 * (c) Olivier Poitrey <rs@dailymotion.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#import "ZYJSDWebImageCompat.h"
#import "UIImage+ZYJTransform.h"

/**
 Return the ZYJTransformed cache key which applied with specify ZYJTransformerKey.

 @param key The original cache key
 @param ZYJTransformerKey The ZYJTransformer key from the ZYJTransformer
 @return The ZYJTransformed cache key
 */
FOUNDATION_EXPORT NSString * _Nullable ZYJSDZYJTransformedKeyForKey(NSString * _Nullable key, NSString * _Nonnull ZYJTransformerKey);

/**
 Return the thumbnailed cache key which applied with specify thumbnailSize and preserveAspectRatio control.
 @param key The original cache key
 @param thumbnailPixelSize The thumbnail pixel size
 @param preserveAspectRatio The preserve aspect ratio option
 @return The thumbnailed cache key
 @note If you have both ZYJTransformer and thumbnail applied for image, call `ZYJSDThumbnailedKeyForKey` firstly and then with `ZYJSDZYJTransformedKeyForKey`.`
 */
FOUNDATION_EXPORT NSString * _Nullable ZYJSDThumbnailedKeyForKey(NSString * _Nullable key, CGSize thumbnailPixelSize, BOOL preserveAspectRatio);

/**
 A ZYJTransformer protocol to ZYJTransform the image load from cache or from download.
 You can provide ZYJTransformer to cache and manager (Through the `ZYJTransformer` property or context option `ZYJSDWebImageContextImageZYJTransformer`).
 
 @note The ZYJTransform process is called from a global queue in order to not to block the main queue.
 */
@protocol ZYJSDImageZYJTransformer <NSObject>

@required
/**
 For each ZYJTransformer, it must contains its cache key to used to store the image cache or query from the cache. This key will be appened after the original cache key generated by URL or from user.

 @return The cache key to appended after the original cache key. Should not be nil.
 */
@property (nonatomic, copy, readonly, nonnull) NSString *ZYJTransformerKey;

/**
 ZYJTransform the image to another image.

 @param image The image to be ZYJTransformed
 @param key The cache key associated to the image. This arg is a hint for image source, not always useful and should be nullable. In the future we will remove this arg.
 @return The ZYJTransformed image, or nil if ZYJTransform failed
 */
- (nullable UIImage *)ZYJTransformedImageWithImage:(nonnull UIImage *)image forKey:(nonnull NSString *)key API_DEPRECATED("The key arg will be removed in the future. Update your code and don't rely on that.", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));

@end

#pragma mark - Pipeline

/**
 Pipeline ZYJTransformer. Which you can bind multiple ZYJTransformers together to let the image to be ZYJTransformed one by one in order and generate the final image.
 @note Because ZYJTransformers are lightweight, if you want to append or arrange ZYJTransformers, create another pipeline ZYJTransformer instead. This class is considered as immutable.
 */
@interface ZYJSDImagePipelineZYJTransformer : NSObject <ZYJSDImageZYJTransformer>

/**
 All ZYJTransformers in pipeline
 */
@property (nonatomic, copy, readonly, nonnull) NSArray<id<ZYJSDImageZYJTransformer>> *ZYJTransformers;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithZYJTransformers:(nonnull NSArray<id<ZYJSDImageZYJTransformer>> *)ZYJTransformers;

@end

// There are some built-in ZYJTransformers based on the `UIImage+ZYJTransformer` category to provide the common image geometry, image blending and image effect process. Those ZYJTransform are useful for static image only but you can create your own to support animated image as well.
// Because ZYJTransformers are lightweight, these class are considered as immutable.
#pragma mark - Image Geometry

/**
 Image round corner ZYJTransformer
 */
@interface ZYJSDImageRoundCornerZYJTransformer: NSObject <ZYJSDImageZYJTransformer>

/**
 The radius of each corner oval. Values larger than half the
 rectangle's width or height are clamped appropriately to
 half the width or height.
 */
@property (nonatomic, assign, readonly) CGFloat cornerRadius;

/**
 A bitmask value that identifies the corners that you want
 rounded. You can use this parameter to round only a subset
 of the corners of the rectangle.
 */
@property (nonatomic, assign, readonly) ZYJSDRectCorner corners;

/**
 The inset border line width. Values larger than half the rectangle's
 width or height are clamped appropriately to half the width
 or height.
 */
@property (nonatomic, assign, readonly) CGFloat borderWidth;

/**
 The border stroke color. nil means clear color.
 */
@property (nonatomic, strong, readonly, nullable) UIColor *borderColor;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithRadius:(CGFloat)cornerRadius corners:(ZYJSDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(nullable UIColor *)borderColor;

@end

/**
 Image resizing ZYJTransformer
 */
@interface ZYJSDImageResizingZYJTransformer : NSObject <ZYJSDImageZYJTransformer>

/**
 The new size to be resized, values should be positive.
 */
@property (nonatomic, assign, readonly) CGSize size;

/**
 The scale mode for image content.
 */
@property (nonatomic, assign, readonly) ZYJSDImageScaleMode scaleMode;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithSize:(CGSize)size scaleMode:(ZYJSDImageScaleMode)scaleMode;

@end

/**
 Image cropping ZYJTransformer
 */
@interface ZYJSDImageCroppingZYJTransformer : NSObject <ZYJSDImageZYJTransformer>

/**
 Image's inner rect.
 */
@property (nonatomic, assign, readonly) CGRect rect;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithRect:(CGRect)rect;

@end

/**
 Image flipping ZYJTransformer
 */
@interface ZYJSDImageFlippingZYJTransformer : NSObject <ZYJSDImageZYJTransformer>

/**
 YES to flip the image horizontally. ⇋
 */
@property (nonatomic, assign, readonly) BOOL horizontal;

/**
 YES to flip the image vertically. ⥯
 */
@property (nonatomic, assign, readonly) BOOL vertical;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical;

@end

/**
 Image rotation ZYJTransformer
 */
@interface ZYJSDImageRotationZYJTransformer : NSObject <ZYJSDImageZYJTransformer>

/**
 Rotated radians in counterclockwise.⟲
 */
@property (nonatomic, assign, readonly) CGFloat angle;

/**
 YES: new image's size is extend to fit all content.
 NO: image's size will not change, content may be clipped.
 */
@property (nonatomic, assign, readonly) BOOL fitSize;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize;

@end

#pragma mark - Image Blending

/**
 Image tint color ZYJTransformer
 */
@interface ZYJSDImageTintZYJTransformer : NSObject <ZYJSDImageZYJTransformer>

/**
 The tint color.
 */
@property (nonatomic, strong, readonly, nonnull) UIColor *tintColor;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithColor:(nonnull UIColor *)tintColor;

@end

#pragma mark - Image Effect

/**
 Image blur effect ZYJTransformer
 */
@interface ZYJSDImageBlurZYJTransformer : NSObject <ZYJSDImageZYJTransformer>

/**
 The radius of the blur in points, 0 means no blur effect.
 */
@property (nonatomic, assign, readonly) CGFloat blurRadius;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithRadius:(CGFloat)blurRadius;

@end

#if ZYJSD_UIKIT || ZYJSD_MAC
/**
 Core Image filter ZYJTransformer
 */
@interface ZYJSDImageFilterZYJTransformer: NSObject <ZYJSDImageZYJTransformer>

/**
 The CIFilter to be applied to the image.
 */
@property (nonatomic, strong, readonly, nonnull) CIFilter *filter;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)ZYJTransformerWithFilter:(nonnull CIFilter *)filter;

@end
#endif
