//
//  SimpleAnimation.m
//

#import "SimpleAnimation.h"

static CGFloat DegreesToRadians(CGFloat degrees)
{
	return degrees * M_PI / 180;
};

struct SimpleAnimationViewState {
	//CGPoint position;
	CGRect frame;
	CGAffineTransform transform;
	CGFloat alpha;
	CATransform3D layerTransform;
};

@implementation SimpleAnimation {
	struct SimpleAnimationViewState _memorizedState;
	BOOL _didStart, _isPlaying, _didMemorizeState;
}

- (void)awakeFromNib {
	[super awakeFromNib];
}

- (void)setAnimationValuesJSON:(NSString *)json {
	self.animationValues = [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
}

- (void)setAnimationKeyPathsJSON:(NSString *)json {
	self.animationKeyPaths = [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
}

- (void)play {
	[self start];
}

- (IBAction)start {
	
	if (_isPlaying) return;
	
	double duration = self.animationDurationMsec/1000;
	
	UIViewAnimationOptions options = 0;
	options |= UIViewAnimationOptionAllowUserInteraction;

	if (self.animationRepeats) {
		options |= UIViewAnimationOptionRepeat;
	}
	if (self.animationRepeatsInReverse) {
		options |= UIViewAnimationOptionAutoreverse;
	}
	if ([self.animationTimingFunction isEqualToString:@"ease-in"]) {
		options |= UIViewAnimationOptionCurveEaseIn;
	}
	else if ([self.animationTimingFunction isEqualToString:@"ease-out"]) {
		options |= UIViewAnimationOptionCurveEaseOut;
	}
	else if ([self.animationTimingFunction isEqualToString:@"ease-in-out"]) {
		options |= UIViewAnimationOptionCurveEaseInOut;
	}
	else {
		options |= UIViewAnimationOptionCurveLinear;
	}
	
	if (self.isReverse) {
		[self memorizeState];
		[self setEndState];
		[UIView animateWithDuration:duration delay:0 options:options animations:^{
			if (self.animationRepeats && self.repeatCount) [UIView setAnimationRepeatCount:self.repeatCount];
			[self setMemorizedState];
		} completion:^(BOOL finished) {
			_isPlaying = NO;
		}];
	}
	else {
		[self memorizeState];
		[UIView animateWithDuration:duration delay:0 options:options animations:^{
			if (self.animationRepeats && self.repeatCount) [UIView setAnimationRepeatCount:self.repeatCount];
			[self setEndState];
		} completion:^(BOOL finished) {
			if (!_isPlaying) return;
			_isPlaying = NO;
			if (!self.remainInFinalState)
				[self setMemorizedState];
		}];
	}
	_isPlaying = YES;
	_didStart = YES;
	
}


- (IBAction)stop {
	_isPlaying = NO;
}


- (void)setEndState {
	CGRect frame = self.view.frame;
	BOOL didChangeFrame = NO;
	for (NSString * key in self.animationKeyPaths) {
		if (![[self.animationKeyPaths valueForKey:key] boolValue]) continue;
		if ([key isEqualToString:@"position"]) {
			frame.origin.x = [[self.animationValues valueForKey:@"x"] doubleValue];
			frame.origin.y = [[self.animationValues valueForKey:@"y"] doubleValue];
			didChangeFrame = YES;
		}
		if ([key isEqualToString:@"size"]) {
			continue; // the size properties don't animate great on iOS
//			frame.size.width = [[self.animationValues valueForKey:@"width"] doubleValue];
//			frame.size.height = [[self.animationValues valueForKey:@"height"] doubleValue];
//			didChangeFrame = YES;
		}
		if ([key isEqualToString:@"opacity"]) {
			double value = [[self.animationValues valueForKey:@"opacity"] doubleValue]/100;
			self.view.alpha = value;
		}
		if ([key isEqualToString:@"transform"]) {
			
			CGAffineTransform t = CGAffineTransformIdentity;

			double scaleX = MAX([[self.animationValues valueForKey:@"scaleX"] floatValue],1)/100;
			double scaleY = MAX([[self.animationValues valueForKey:@"scaleY"] floatValue],1)/100;
			t = CGAffineTransformScale(t, scaleX, scaleY);

			double r = [[self.animationValues valueForKey:@"rotate"] floatValue];
			if (r) { t = CGAffineTransformRotate(t, DegreesToRadians(r)); }
			
			self.view.transform = t;
			
/*			if (r) {
				CABasicAnimation* rotationAnimation;
				rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
				rotationAnimation.toValue = [NSNumber numberWithFloat: DegreesToRadians(r)];
				rotationAnimation.duration = duration;
				rotationAnimation.cumulative = YES;
				rotationAnimation.repeatCount = 1.0;
				rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
				[self.view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
			}*/
			
		}
		
	}
	if (didChangeFrame) {
		CGRect r = self.view.frame;
		r.origin = frame.origin;
		self.view.frame = r;
	}
}

- (void)setMemorizedState {
	self.view.transform = _memorizedState.transform;
	self.view.alpha = _memorizedState.alpha;
	self.view.frame = _memorizedState.frame;
}

- (void)reset {
	[self stop];
	[self setMemorizedState];
}

- (void)memorizeState {
	if (_didMemorizeState) return;
	_memorizedState.alpha = self.view.alpha;
	_memorizedState.frame = self.view.frame;
	_memorizedState.transform = self.view.transform;
	_didMemorizeState = YES;
}

- (void)viewWillAppear:(BOOL)animated {
	if (self.animationStartsImmediately && (!_didStart || self.animationRepeats)) {
		[self start];
	}
}

@end
