//
//  XWCoolAnimator+XWVerticalLines.m
//  XWTransitionDemo
//
//  Created by wazrx on 16/6/14.
//  Copyright © 2016年 wazrx. All rights reserved.
//

#import "XWCoolAnimator+XWLines.h"

@implementation XWCoolAnimator (XWLines)

static inline float XWRandomFloat(float max, float min){
    return ((float)arc4random() / 0x100000000) * (max - min) + min;
}

- (void)xw_setLinesToAnimation:(id<UIViewControllerContextTransitioning>)transitionContext vertical:(BOOL)vertical {
    [self _xw_animateTransition:transitionContext duration:self.toDuration to:YES vertical:vertical];
    
}

- (void)xw_setLinesBackAnimation:(id<UIViewControllerContextTransitioning>)transitionContext vertical:(BOOL)vertical {
    [self _xw_animateTransition:transitionContext duration:self.toDuration to:NO vertical:vertical];
    
}


#define HLINEHEIGHT 4.0
- (void)_xw_animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext duration:(NSTimeInterval)duration to:(BOOL)flag vertical:(BOOL)vertical{
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toVC.view;
    UIView *containerView = [transitionContext containerView];
    [containerView insertSubview:toView atIndex:0];
    NSArray *outgoingLineViews = [self _xw_lineViews:fromVC.view intoSlicesOfDis:HLINEHEIGHT Offset:fromVC.view.frame.origin.y containerView:containerView vertical:vertical];
    NSArray *incomingLineViews = [self _xw_lineViews:toView intoSlicesOfDis:HLINEHEIGHT Offset:toView.frame.origin.y containerView:containerView vertical:vertical];
    CGFloat toViewStart = vertical ? toView.frame.origin.y : toView.frame.origin.x;
    BOOL presenting = flag;
    vertical ? [self _xw_repositionViewSlices:incomingLineViews moveFirstFrameUp:NO]:[self _xw_repositionViewSlices:incomingLineViews moveLeft:!presenting];
    fromVC.view.hidden = YES;
    toView.hidden = YES;
    [UIView animateWithDuration:duration - 0.01 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        vertical ? [self _xw_repositionViewSlices:outgoingLineViews moveFirstFrameUp:YES] : [self _xw_repositionViewSlices:outgoingLineViews moveLeft:presenting];
        [self _xw_resetViewSlices:incomingLineViews toOrigin:toViewStart vertical:vertical];
    } completion:^(BOOL finished) {
        fromVC.view.hidden = NO;
        toView.hidden = NO;
        [toView setNeedsUpdateConstraints];
        for (UIView *v in incomingLineViews) {
            [v removeFromSuperview];
        }
        for (UIView *v in outgoingLineViews) {
            [v removeFromSuperview];
        }
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

- (UIImage *)_xw_ImageFromsnapshotView:(UIView *)view{
    CALayer *layer = view.layer;
    UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.opaque, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [layer renderInContext:context];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

//弃用了原作者的截取若干小图的方法,由于toView刚开始无法截图,原作者采用延迟0.001秒后来截图,但是这种方式不是对手势和转场失败的效果有很大的干扰,所以我转换思路换了一种方式实现了小图,采用的是contentsRect
- (NSArray<UIView *> *)_xw_lineViews:(UIView *)view intoSlicesOfDis:(float)dis Offset:(float)yOffset containerView:(UIView *)containerView vertical:(BOOL)vertical{
    CGFloat width = vertical ? CGRectGetHeight(view.frame) : CGRectGetWidth(view.frame);
    CGFloat height = !vertical ? CGRectGetHeight(view.frame) : CGRectGetWidth(view.frame);
    UIImage *img = [self _xw_ImageFromsnapshotView:view];
    NSMutableArray *lineViews = [NSMutableArray array];
    for (int i = 0; i < height; i += dis) {
        CGRect subrect = vertical ? CGRectMake(i, 0, dis, width) : CGRectMake(0, i, width, dis);
        UIView *subsnapshot = [UIView new];
        subsnapshot.layer.contents= (__bridge id)img.CGImage;
        subsnapshot.layer.contentsRect = vertical ? CGRectMake((float)i / view.frame.size.width, 0.0,  dis / view.frame.size.width, 1.0) : CGRectMake(0, (float)i / view.frame.size.height, 1.0, dis / view.frame.size.height);
        subrect.origin.x += yOffset;
        subsnapshot.frame = subrect;
        [lineViews addObject:subsnapshot];
        [containerView addSubview:subsnapshot];
    }
    return lineViews;
}


-(void)_xw_repositionViewSlices:(NSArray *)views moveLeft:(BOOL)left{
    CGRect frame;
    float width;
    for (UIView *line in views) {
        frame = line.frame;
        width = CGRectGetWidth(frame) * XWRandomFloat(1.0, 8.0);
        frame.origin.x += (left)?-width:width;
        line.frame = frame;
    }
}

-(void)_xw_repositionViewSlices:(NSArray *)views moveFirstFrameUp:(BOOL)startUp{
    
    BOOL up = startUp;
    CGRect frame;
    float height;
    for (UIView *line in views) {
        frame = line.frame;
        height = CGRectGetHeight(frame) * XWRandomFloat(1.0, 4.0);
        frame.origin.y += (up)?-height:height;
        line.frame = frame;
        
        up = !up;
    }
}

-(void)_xw_resetViewSlices:(NSArray *)views toOrigin:(CGFloat)o vertical:(BOOL)vertical{
    CGRect frame;
    for (UIView *line in views) {
        frame = line.frame;
        if (vertical) {
            frame.origin.y = o;
        }else{
            frame.origin.x = o;
        }
        line.frame = frame;
    }
}

@end