//
//  CLNavigationController.swift

//
//  Created by Leon on 2025/7/12.
//

import UIKit

protocol NavigationControllerDelegate: NSObjectProtocol {
    func popGestureRecognizerShouldBegin() -> Bool
}

extension NavigationControllerDelegate {
    func popGestureRecognizerShouldBegin() -> Bool {
        return true
    }
}

class CLNavigationController: UINavigationController {

    weak var popDelegate: NavigationControllerDelegate?

    private(set) var pan: UIPanGestureRecognizer!

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationBar.isHidden = true
        modalPresentationStyle = .fullScreen
        addFullScreenPan()
    }

    override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        if viewControllers.count > 0 {
            if viewController is CLBaseViewController {
                let vc = viewController as! CLBaseViewController
                vc.hiddenBackButton(of: false)
            }
            viewController.hidesBottomBarWhenPushed = true
        }
        // 如果viewController已经在navigationStack中，则不进行push
        if viewControllers.contains(viewController) {
            return
        }

        super.pushViewController(viewController, animated: animated)
    }

    override open var childForStatusBarStyle: UIViewController? {
        return topViewController
    }

    private func addFullScreenPan() {
        // 1.获取系统的Pop手势
        guard let systemGes = interactivePopGestureRecognizer else { return }
        // 2.获取手势添加到的View中
        guard let gesView = systemGes.view else { return }
        // 3.取出target
        let targets = systemGes.value(forKey: "_targets") as? [NSObject]
        guard let targetObjc = targets?.first else { return }
        guard let target = targetObjc.value(forKey: "target") else { return }
        // 4.取出action
        let action = Selector(("handleNavigationTransition:"))
        // 5. 创建自己的pan手势
        pan = UIPanGestureRecognizer()
        gesView.addGestureRecognizer(pan)
        pan.addTarget(target, action: action)
        pan.delegate = self
    }

    /// 关闭全屏 保留系统手势
    func disabledFullScreenPan() {
        pan.isEnabled = false
        interactivePopGestureRecognizer?.delegate = self
    }

    /// 开启全屏
    func enabledFullScreenPan() {
        pan.isEnabled = true
    }

    /// 关闭全屏 和 系统
    func disabledPopGesture() {
        pan.isEnabled = false
        interactivePopGestureRecognizer?.isEnabled = false
    }

    /// 开启全屏 和 系统
    func enabledPopGesture() {
        pan.isEnabled = true
        interactivePopGestureRecognizer?.isEnabled = true
    }
}

extension CLNavigationController: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if viewControllers.count <= 1 {
            return false
        }
        if value(forKey: "_isTransitioning") as? Bool ?? false {
            return false
        }
        let translation = gestureRecognizer.location(in: gestureRecognizer.view)
        if translation.x <= 0 {
            return false
        }

        if let popDelegate = popDelegate {
            return popDelegate.popGestureRecognizerShouldBegin()
        }
        return true
    }
}


// MARK: - 解决全屏滑动时的手势冲突

extension UIScrollView: @retroactive UIGestureRecognizerDelegate {
    // 当UIScrollView在水平方向滑动到第一个时，默认是不能全屏滑动返回的，通过下面的方法可实现其滑动返回。
    override open func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if panBack(gestureRecognizer: gestureRecognizer) {
            return false
        }
        return true
    }

    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer) -> Bool {
        if panBack(gestureRecognizer: gestureRecognizer) {
            return true
        }
        return false
    }

    func panBack(gestureRecognizer: UIGestureRecognizer) -> Bool {
        if gestureRecognizer == panGestureRecognizer {
            let point = panGestureRecognizer.translation(in: self)
            let state = gestureRecognizer.state

            // 设置手势滑动的位置距屏幕左边的区域
            let locationDistance = UIScreen.main.bounds.size.width

            if state == UIGestureRecognizer.State.began || state == UIGestureRecognizer.State.possible {
                let location = gestureRecognizer.location(in: self)
                if point.x > 0, location.x < locationDistance, contentOffset.x <= 0 {
                    return true
                }
            }
        }
        return false
    }
}
