//
// ImageUtils.m
// MyProject
//
// Created by haibara on 6/19/15.
//
//

#import "ImageUtils.h"
#import <SVGKit/SVGKit.h>

@implementation ImageUtils

#pragma mark - Public

+ (UIImage *)drawImage:(UIImage *)image atRect:(CGRect)rect {
	UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale);
	[image drawAtPoint:rect.origin];
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

+ (UIImage *)imageWithColor:(UIColor *)fillColor {
	CGRect rect = CGRectMake(0, 0, 1, 1);
	UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
	[fillColor set];
	UIRectFill(rect);
	UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return image;
}

+ (UIImage *)adjustImage:(UIImage *)image tintColor:(UIColor *)tintColor {
	UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
	CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
	[tintColor set];
	UIRectFill(rect);
	[image drawInRect:rect blendMode:kCGBlendModeDestinationIn alpha:1];
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

+ (UIImage *)imageNamed:(NSString *)name tintColor:(UIColor *)tintColor {
	return [self adjustImage:[UIImage imageNamed:name] tintColor:tintColor];
}

+ (UIImage *)cropImage:(UIImage *)image toSize:(CGSize)size {
	CGRect rect = CGRectMake(0, 0, size.width, size.height);
	return [self cropImage:image inRect:rect];
}

+ (UIImage *)cropImage:(UIImage *)image inRect:(CGRect)rect {
	CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, CGRectApplyAffineTransform(rect, CGAffineTransformMakeScale(image.scale, image.scale)));
	UIImage *newImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
	CGImageRelease(imageRef);
	return newImage;
}

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size {
	return [self scaleImage:image toSize:size interpolationQuality:kCGInterpolationDefault];
}

+ (UIImage *)scaleImage:(UIImage *)image toWidth:(CGFloat)width {
	return [self scaleImage:image byFactor:width / image.size.width];
}

+ (UIImage *)scaleImage:(UIImage *)image toHeight:(CGFloat)height {
	return [self scaleImage:image byFactor:height / image.size.height];
}

+ (UIImage *)scaleImage:(UIImage *)image byFactor:(CGFloat)factor {
	return [UIImage imageWithCGImage:image.CGImage scale:image.scale / factor orientation:image.imageOrientation];
}

+ (UIImage *)scaleCIIImage:(CIImage *)image toSize:(CGSize)size {
	CGRect rect = CGRectMake(0, 0, size.width, size.height);
	return [self drawImage:[UIImage imageWithCIImage:image] inRect:rect interpolationQuality:kCGInterpolationNone];
}

+ (UIImage *)scaleSVGImageNamed:(NSString *)name toSize:(CGSize)size {
	SVGKImage *svgImage = [SVGKImage imageNamed:name];
	svgImage.size = size;
	return svgImage.UIImage;
}

+ (UIImage *)scaleSVGImageNamed:(NSString *)name byFactor:(CGFloat)factor {
	SVGKImage *svgImage = [SVGKImage imageNamed:name];
	svgImage.size = CGSizeApplyAffineTransform(svgImage.size, CGAffineTransformMakeScale(factor, factor));
	return svgImage.UIImage;
}

+ (UIImage *)rotateImage:(UIImage *)image byRadians:(CGFloat)radians {
	UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
	CGContextRef context = UIGraphicsGetCurrentContext();
	CGContextTranslateCTM(context, image.size.width * 0.5, image.size.height * 0.5);
	CGContextRotateCTM(context, radians);
	[image drawAtPoint:CGPointMake(image.size.width * -0.5, image.size.height * -0.5)];
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

+ (UIImage *)rotateImage:(UIImage *)image byDegrees:(CGFloat)degrees {
	return [self rotateImage:image byRadians:DEGREES_TO_RADIANS(degrees)];
}

+ (UIImage *)xMontageWithImages:(NSArray *)images border:(CGFloat)border {
	return [self montageWithImages:images tile:CGPointMake(1, 0) border:border];
}

+ (UIImage *)montageWithImages:(NSArray *)images tile:(CGPoint)tile border:(CGFloat)border {
	if (CGPointEqualToPoint(tile, CGPointZero)) {
		return nil;
	}
	CGFloat width = 0;
	CGFloat height = 0;
	CGFloat scale = 0;
	NSInteger rows = tile.x > 0 ? tile.x : (int)ceilf(images.count / tile.y);
	NSInteger cols = tile.y > 0 ? tile.y : (int)ceilf(images.count / tile.x);
	for (NSInteger m = 0; m < rows; m++) {
		CGFloat w = 0;
		for (NSInteger n = 0; n < cols; n++) {
			NSInteger i = m * cols + n;
			if (i >= images.count) {
				continue;
			}
			UIImage *image = images[i];
			w += image.size.width;
			height = MAX(height, image.size.height);
			scale = MAX(scale, image.scale);
		}
		width = MAX(width, w);
	}
	CGSize newSize = CGSizeMake(width + (cols + 1) * border, height + (rows + 1) * border);
	UIGraphicsBeginImageContextWithOptions(newSize, NO, scale);
	CGFloat x = 0;
	CGFloat y = 0;
	for (NSInteger m = 0; m < rows; m++) {
		y += border;
		CGFloat h = 0;
		for (NSInteger n = 0; n < cols; n++) {
			NSInteger i = m * cols + n;
			if (i >= images.count) {
				continue;
			}
			x += border;
			UIImage *image = images[i];
			CGRect rect = CGRectMake(x, y, image.size.width, image.size.height);
			[image drawInRect:rect];
			x += image.size.width;
			h = MAX(h, image.size.height);
		}
		y += h;
	}
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

+ (UIImage *)xMontageWithImages:(NSArray *)images countOfSingleRow:(CGFloat)count border:(CGFloat)border {
	if (images.count > 0 && count >= 0) {
		if (count == 0) {
			count = images.count;
		}
		CGFloat rowCount = ceilf(images.count / count);
		NSMutableArray *arrays = [NSMutableArray array];
		for (int row = 0; row < rowCount; ++row) {
			NSMutableArray *array = [NSMutableArray array];
			[arrays addObject:array];
		}
		for (int index = 0; index < images.count; ++index) {
			CGFloat i = floorf(index / count);
			[arrays[(NSInteger)i] addObject:images[index]];
		}
		CGFloat width = 0;
		CGFloat height = 0;
		CGFloat scale = 0;
		for (NSArray *array in arrays) {
			CGFloat tmpW = 0;
			CGFloat tmpH = 0;
			for (UIImage *image in array) {
				tmpW += image.size.width;
				tmpH = MAX(tmpH, image.size.height);
				scale = MAX(scale, image.scale);
			}
			width = MAX(width, tmpW);
			height += tmpH;
		}
		CGSize newImgSize = CGSizeMake(width + (count + 1) * border, height + (rowCount + 1) * border);
		UIGraphicsBeginImageContextWithOptions(newImgSize, NO, scale);
		CGFloat startX = 0;
		CGFloat startY = 0;
		for (NSArray *array in arrays) {
			startX = 0;
			startY += border;
			CGFloat tmpH = 0;
			for (UIImage *image in array) {
				startX += border;
				CGRect rect = CGRectMake(startX, startY, image.size.width, image.size.height);
				[image drawInRect:rect];
				startX += image.size.width;
				tmpH = MAX(tmpH, image.size.height);
			}
			startY += tmpH;
		}
		UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
		UIGraphicsEndImageContext();
		return newImage;
	}
	return nil;
}

+ (UIImage *)snapshotImageWithView:(UIView *)view {
// UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0);
// [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
// UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// UIGraphicsEndImageContext();
// return newImage;
	UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
	[view.layer renderInContext:UIGraphicsGetCurrentContext()];
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

#pragma mark - Private

+ (UIImage *)drawImage:(UIImage *)image inRect:(CGRect)rect interpolationQuality:(CGInterpolationQuality)quality {
	UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale);
	CGContextSetInterpolationQuality(UIGraphicsGetCurrentContext(), quality);
	[image drawInRect:rect];
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	return newImage;
}

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size interpolationQuality:(CGInterpolationQuality)quality {
	CGRect rect = CGRectMake(0, 0, size.width, size.height);
	return [self drawImage:image inRect:rect interpolationQuality:quality];
}

@end
