//
//  DuckAnimationController.swift
//  Duckable
//
//  Created by Shadowfacts on 11/7/22.
//

import UIKit

@available(iOS 16.0, *)
class DuckAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    let owner: DuckableContainerViewController
    let needsShrinkAnimation: Bool
    
    init(owner: DuckableContainerViewController, needsShrinkAnimation: Bool) {
        self.owner = owner
        self.needsShrinkAnimation = needsShrinkAnimation
    }
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.2
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard case .ducked(let duckable, placeholder: let placeholder) = owner.state,
              let presented = transitionContext.viewController(forKey: .from) else {
            transitionContext.completeTransition(false)
            return
        }

        guard transitionContext.isAnimated else {
            transitionContext.completeTransition(true)
            return
        }
        
        let container = transitionContext.containerView
        

        if needsShrinkAnimation {
            
            duckable.duckableViewControllerWillAnimateDuck(withDuration: 0.2, afterDelay: 0.2)

            let presentedFrameInContainer = container.convert(presented.view.bounds, from: presented.view)
            let heightToSlide = container.bounds.height - container.safeAreaInsets.bottom - detentHeight - presentedFrameInContainer.minY

            let slideAnimator = UIViewPropertyAnimator(duration: 0.4, dampingRatio: 1)
            slideAnimator.addAnimations {
                container.transform = CGAffineTransform(translationX: 0, y: heightToSlide + 10)
            }
            slideAnimator.addCompletion { _ in
                duckable.duckableViewControllerDidFinishAnimatingDuck()
                transitionContext.completeTransition(true)
            }
            slideAnimator.startAnimation()

            placeholder.view.transform = CGAffineTransform(translationX: 0, y: 10)
            let bounceAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .linear) {
                placeholder.view.transform = .identity
                container.transform = CGAffineTransform(translationX: 0, y: heightToSlide)
            }
            bounceAnimator.startAnimation(afterDelay: 0.3)

            let fadeAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .linear) {
                presented.view.layer.opacity = 0
            }
            fadeAnimator.addCompletion { _ in
                presented.view.layer.opacity = 1
            }
            fadeAnimator.startAnimation(afterDelay: 0.3)

        } else {
            
            duckable.duckableViewControllerWillAnimateDuck(withDuration: 0.2, afterDelay: 0)

            placeholder.view.transform = CGAffineTransform(translationX: 0, y: 10)
            let bounceAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .linear) {
                placeholder.view.transform = .identity
                container.transform = CGAffineTransform(translationX: 0, y: -10)
            }
            bounceAnimator.startAnimation(afterDelay: 0.2)

            let fadeAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .linear) {
                presented.view.layer.opacity = 0
            }
            fadeAnimator.addCompletion { _ in
                presented.view.layer.opacity = 1
                duckable.duckableViewControllerDidFinishAnimatingDuck()
                transitionContext.completeTransition(true)
            }
            fadeAnimator.startAnimation(afterDelay: 0.2)
        }
    }
}
