//
//  LargeImageShrinkAnimationController.swift
//  Tusker
//
//  Created by Shadowfacts on 9/1/18.
//  Copyright © 2018 Shadowfacts. All rights reserved.
//

import UIKit
import TuskerComponents

class LargeImageShrinkAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    
    let interactionController: LargeImageInteractionController?
    
    init(interactionController: LargeImageInteractionController?) {
        self.interactionController = interactionController
    }
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.2
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from) as? LargeImageAnimatableViewController,
            let toVC = transitionContext.viewController(forKey: .to) else {
                return
        }
        
        if UIAccessibility.prefersCrossFadeTransitions && !transitionContext.isInteractive {
            animateCrossFadeTransition(using: transitionContext)
            return
        }
        
        guard let sourceView = fromVC.animationSourceView,
            let sourceFrame = fromVC.sourceViewFrame(in: toVC.view),
            let image = fromVC.animationImage else {
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                return
        }

        // use alpha, becaus isHidden makes stack views re-layout
        sourceView.alpha = 0

        let containerView = transitionContext.containerView
        
        let originalVCFrame = fromVC.view.frame
        var originalFrameSize = originalVCFrame.inset(by: fromVC.view.safeAreaInsets).size
        let newWidth = originalFrameSize.width / image.size.width
        let newHeight = originalFrameSize.height / image.size.height
        if newHeight < newWidth {
            originalFrameSize.width = newHeight * image.size.width
        } else {
            originalFrameSize.height = newWidth * image.size.height
        }
        let originalFrame = CGRect(origin: CGPoint(x: originalVCFrame.midX - originalFrameSize.width / 2, y: originalVCFrame.midY - originalFrameSize.height / 2), size: originalFrameSize)

        let imageView = GIFImageView(frame: originalFrame)
        imageView.image = image
        if let gifController = (sourceView as? GIFImageView)?.gifController {
            gifController.attach(to: imageView)
            // todo: this might not be necessary, the large image content view should have started it
            gifController.startAnimating()
        }
        imageView.contentMode = .scaleAspectFill
        imageView.layer.cornerRadius = 0
        imageView.layer.masksToBounds = true
        
        let blackView = UIView(frame: originalVCFrame)
        blackView.backgroundColor = .black
        blackView.alpha = 1
        
        // Save the old superview of toVC so we can move it back after the animation.
        // It would be better to just not move toVC and instead remove from fromVC from the
        // containerView so that toVC is visible behind it, but that doens't work for some reason
        // (the entire screen just goes black, not even the contents of the containerView appear).
        let oldSuperview = toVC.view.superview
        
        containerView.addSubview(toVC.view)
        containerView.addSubview(blackView)
        containerView.addSubview(imageView)
        
        let duration = transitionDuration(using: transitionContext)
        UIView.animate(withDuration: duration, animations: {
            imageView.frame = sourceFrame
            imageView.layer.cornerRadius = sourceView.layer.cornerRadius
            imageView.layer.maskedCorners = sourceView.layer.maskedCorners
            blackView.alpha = 0
        }, completion: { _ in
            blackView.removeFromSuperview()
            imageView.removeFromSuperview()
            if transitionContext.transitionWasCancelled {
                toVC.view.removeFromSuperview()
            }
            
            sourceView.alpha = 1

            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            
            // move the toVC back to the view that it was in before
            oldSuperview?.addSubview(toVC.view)
        })
    }
    
    func animateCrossFadeTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from) as? LargeImageAnimatableViewController,
              let toVC = transitionContext.viewController(forKey: .to) else {
            return
        }
        
        transitionContext.containerView.addSubview(toVC.view)
        transitionContext.containerView.addSubview(fromVC.view)
        
        let duration = transitionDuration(using: transitionContext)
        UIView.animate(withDuration: duration) {
            fromVC.view.alpha = 0
        } completion: { (_) in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
    }
    
}
