//
//  DDViewControllerAnimatedTransition.m
//  DDAnimationsKit_Private
//  Created by DDIsFriend on 2022/9/20.

#import "DDViewControllerAnimatedTransition.h"
#import <objc/runtime.h>

#define VIEWCONTROLLER_ANIMATEDTRANSITION_DURATION 0.25

@implementation DDViewControllerAnimatedTransition

- (instancetype)initWithTransitionType:(DDViewControllerAnimatedTransitionType)animatedTransitionType{
    self = [super init];
    if (self) {
        self.animatedTransitionType = animatedTransitionType;
    }
    return self;
}

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return VIEWCONTROLLER_ANIMATEDTRANSITION_DURATION;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    
    switch (self.animatedTransitionType) {
        case DDViewControllerAnimatedTransitionPush:
            [self pushAnimation:transitionContext];
            break;
            
        case DDViewControllerAnimatedTransitionPop:
            [self popAnimation:transitionContext];
            break;
            
        default:
            break;
    }
}

-(void)pushAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
    
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *container = [transitionContext containerView];
    
    CGRect fromVCRect = [transitionContext initialFrameForViewController:fromVC];
    fromVCRect.origin.x = 0;
    fromVCRect.origin.y = 0;
    fromVCRect.size = container.frame.size;
    fromVC.view.frame = fromVCRect;
    
    CGRect fromVCToRect = fromVC.view.frame;
    fromVCToRect.origin.x = container.frame.size.width * 1 * (-0.5);
    
    CGRect toVCRect = [transitionContext initialFrameForViewController:fromVC];
    toVCRect.origin.x = container.frame.size.width;
    toVCRect.origin.y = 0;
    toVCRect.size = container.frame.size;
    toVC.view.frame = toVCRect;
    
    CGRect toVCToRect = toVC.view.frame;
    toVCToRect.origin.x = 0;

    UIBezierPath *path = [UIBezierPath bezierPathWithRect:toVC.view.bounds];
    path.lineWidth = 3;
    toVC.view.layer.shadowPath = path.CGPath;
    toVC.view.layer.shadowColor = UIColor.darkGrayColor.CGColor;
    toVC.view.layer.shadowOpacity = 3;
    
    UIView *navigationBarSnapshot = [fromVC.navigationController.view resizableSnapshotViewFromRect:CGRectMake(0, 0, container.frame.size.width, CGRectGetMaxY(fromVC.navigationController.navigationBar.frame)) afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
    fromVC.dd_transitionNavigationBarSnapshot = navigationBarSnapshot;
    [fromVC.view addSubview:navigationBarSnapshot];
    
    if (([fromVC.navigationController.parentViewController isKindOfClass:[UITabBarController class]] == YES) && (fromVC.navigationController.viewControllers.count == 2)) {
        UITabBarController *tabBarController = (UITabBarController *)fromVC.navigationController.parentViewController;
        UIView *tabBarSnapshot = [tabBarController.tabBar resizableSnapshotViewFromRect:CGRectMake(0, 0, container.frame.size.width, CGRectGetMaxY(tabBarController.tabBar.frame) - CGRectGetMinY(tabBarController.tabBar.frame)) afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
        fromVC.dd_transitionTabBarSnapshot = tabBarSnapshot;
        tabBarSnapshot.frame = CGRectMake(0, CGRectGetMaxY(fromVC.view.frame) - tabBarSnapshot.bounds.size.height, tabBarSnapshot.bounds.size.width, tabBarSnapshot.bounds.size.height);
        [fromVC.view addSubview:tabBarSnapshot];
    }
    
    if (fromVC.dd_transitionTabBarSnapshot != nil) {
        fromVC.tabBarController.tabBar.hidden = YES;
    }
    
    [fromVC.navigationController.view addSubview:fromVC.view];
    [fromVC.navigationController.view addSubview:toVC.view];
    
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        fromVC.view.frame = fromVCToRect;
        toVC.view.frame = toVCToRect;

    } completion:^(BOOL finished) {
    
        if (![transitionContext transitionWasCancelled]){
            [fromVC.dd_transitionNavigationBarSnapshot removeFromSuperview];
            [fromVC.dd_transitionTabBarSnapshot removeFromSuperview];
            [fromVC.view removeFromSuperview];
            [toVC.view removeFromSuperview];
            [container addSubview:toVC.view];
        }else{
            [fromVC.dd_transitionNavigationBarSnapshot removeFromSuperview];
            fromVC.dd_transitionNavigationBarSnapshot = nil;
            if (fromVC.dd_transitionTabBarSnapshot != nil) {
                [fromVC.dd_transitionTabBarSnapshot removeFromSuperview];
                fromVC.dd_transitionTabBarSnapshot = nil;
            }
            [fromVC.view removeFromSuperview];
            [toVC.view removeFromSuperview];
            [container addSubview:fromVC.view];
        }
        
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
    
}

-(void)popAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
    
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *container = [transitionContext containerView];

    CGRect fromVCRect = [transitionContext initialFrameForViewController:fromVC];
    fromVCRect.origin.x = 0;
    fromVCRect.origin.y = 0;
    fromVCRect.size = container.frame.size;
    fromVC.view.frame = fromVCRect;

    CGRect fromVCToRect = fromVC.view.frame;
    fromVCToRect.origin.x = container.frame.size.width;
    
    CGRect toVCRect = [transitionContext initialFrameForViewController:fromVC];
    toVCRect.origin.x = container.frame.size.width * 1 * (-0.5);
    toVCRect.origin.y = 0;
    toVCRect.size = container.frame.size;
    toVC.view.frame = toVCRect;
    
    CGRect toVCToRect = toVC.view.frame;
    toVCToRect.origin.x = 0;
    
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:fromVC.view.bounds];
    path.lineWidth = 3;
    fromVC.view.layer.shadowPath = path.CGPath;
    fromVC.view.layer.shadowColor = UIColor.darkGrayColor.CGColor;
    fromVC.view.layer.shadowOpacity = 3;
    
    UIView *navigationBarSnapshot = [fromVC.navigationController.view resizableSnapshotViewFromRect:CGRectMake(0, 0, container.frame.size.width, CGRectGetMaxY(fromVC.navigationController.navigationBar.frame)) afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
    fromVC.dd_transitionNavigationBarSnapshot = navigationBarSnapshot;
    [fromVC.view addSubview:navigationBarSnapshot];
    [toVC.view addSubview:toVC.dd_transitionNavigationBarSnapshot];
    
    if (toVC.dd_transitionTabBarSnapshot != nil) {
        [toVC.view addSubview:toVC.dd_transitionTabBarSnapshot];
        toVC.tabBarController.tabBar.hidden = YES;
    }

    [fromVC.navigationController.view addSubview:toVC.view];
    [fromVC.navigationController.view addSubview:fromVC.view];
    
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        
        fromVC.view.frame = fromVCToRect;
        toVC.view.frame = toVCToRect;
        
    } completion:^(BOOL finished){

        if (![transitionContext transitionWasCancelled]){
            [fromVC.dd_transitionNavigationBarSnapshot removeFromSuperview];
            fromVC.dd_transitionNavigationBarSnapshot = nil;
            [fromVC.view removeFromSuperview];
            [toVC.dd_transitionNavigationBarSnapshot removeFromSuperview];
            toVC.dd_transitionNavigationBarSnapshot = nil;
            if (toVC.dd_transitionTabBarSnapshot != nil) {
                [toVC.dd_transitionTabBarSnapshot removeFromSuperview];
                toVC.dd_transitionTabBarSnapshot = nil;
                toVC.tabBarController.tabBar.hidden = NO;
            }
            [toVC.view removeFromSuperview];
            [container addSubview:toVC.view];
            toVC.view.frame = container.bounds;
        }else{
            [fromVC.dd_transitionNavigationBarSnapshot removeFromSuperview];
            fromVC.dd_transitionNavigationBarSnapshot = nil;
            [fromVC.view removeFromSuperview];
            [toVC.view removeFromSuperview];
            [container addSubview:fromVC.view];
            fromVC.view.frame = container.bounds;
        }
        
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
    
}

@end

@implementation UIViewController (Transition)

// MARK: <NavigationController Push Transition Snapshot>
- (UIView *)dd_transitionNavigationBarSnapshot{
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setDd_transitionNavigationBarSnapshot:(UIView *)dd_transitionNavigationBarSnapshot{
    objc_setAssociatedObject(self, @selector(dd_transitionNavigationBarSnapshot), dd_transitionNavigationBarSnapshot, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

// MARK: <TabBarController Push Transition Snapshot>
- (UIView *)dd_transitionTabBarSnapshot{
    return  objc_getAssociatedObject(self, _cmd);
}

- (void)setDd_transitionTabBarSnapshot:(UIView *)dd_transitionTabBarSnapshot{
    objc_setAssociatedObject(self, @selector(dd_transitionTabBarSnapshot), dd_transitionTabBarSnapshot, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
