+ (CAAnimation*)reverseAnimation:(CAAnimation*)anim totalDuration:(CGFloat)totalDuration{
CGFloat duration = anim.duration + (anim.autoreverses ? anim.duration : 0);
duration = anim.repeatCount > 1 ? duration * anim.repeatCount : duration;

CGFloat endTime = anim.beginTime + duration;
CGFloat reverseStartTime = totalDuration - endTime;

CAAnimation *newAnim;
//Reverse timing function
void (^reverseTimingFunction)(CAAnimation*) = ^(CAAnimation *theAnim){
CAMediaTimingFunction *timingFunction = theAnim.timingFunction;
if (timingFunction) {
float first[2];
float second[2];
[timingFunction getControlPointAtIndex:1 values:first];
[timingFunction getControlPointAtIndex:2 values:second];
theAnim.timingFunction = [CAMediaTimingFunction functionWithControlPoints:1-second[0] :1-second[1] :1-first[0] :1-first[1]];
}
};

//Reverse animation values appropriately
if ([anim isKindOfClass:[CABasicAnimation class]]) {
CABasicAnimation *basicAnim = (CABasicAnimation*)anim;

if (!anim.autoreverses) {
id fromValue = basicAnim.toValue;
basicAnim.toValue = basicAnim.fromValue;
basicAnim.fromValue = fromValue;
reverseTimingFunction(basicAnim);
}
basicAnim.beginTime = reverseStartTime;

if (reverseStartTime > 0) {
CAAnimationGroup *groupAnim = [CAAnimationGroup animation];
groupAnim.animations = @[basicAnim];
groupAnim.duration = [self maxDurationFromAnimations:groupAnim.animations];
[groupAnim.animations setValue:kCAFillModeBoth forKeyPath:@"fillMode"];
newAnim = groupAnim;
}else newAnim = basicAnim;
}
else if ([anim isKindOfClass:[CAKeyframeAnimation class]]) {
CAKeyframeAnimation *keyAnim = (CAKeyframeAnimation*)anim;

if (!anim.autoreverses) {
NSArray *values = [[keyAnim.values reverseObjectEnumerator] allObjects];
keyAnim.values = values;
reverseTimingFunction(keyAnim);
}
keyAnim.beginTime = reverseStartTime;

if (reverseStartTime > 0) {
CAAnimationGroup *groupAnim = [CAAnimationGroup animation];
groupAnim.animations = @[keyAnim];
groupAnim.duration = [self maxDurationFromAnimations:groupAnim.animations];
[groupAnim.animations setValue:kCAFillModeBoth forKeyPath:@"fillMode"];
newAnim = groupAnim;
}else newAnim = keyAnim;

}
else if ([anim isKindOfClass:[CAAnimationGroup class]]) {
CAAnimationGroup *groupAnim = (CAAnimationGroup*)anim;
NSMutableArray *newSubAnims = [NSMutableArray arrayWithCapacity:groupAnim.animations.count];
for (CAAnimation *subAnim in groupAnim.animations) {
CAAnimation *newSubAnim = [self reverseAnimation:subAnim totalDuration:totalDuration];
[newSubAnims addObject:newSubAnim];
}
groupAnim.animations = newSubAnims;
[groupAnim.animations setValue:kCAFillModeBoth forKeyPath:@"fillMode"];
groupAnim.duration = [self maxDurationFromAnimations:newSubAnims];
newAnim = groupAnim;
}else newAnim = anim;

return newAnim;
}
