import UIKit
import os.log
import AVFoundation
import RxSwift
import PKHUD

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let windowScene = (scene as? UIWindowScene) else { return }
        guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
        
        if let activity = connectionOptions.userActivities.first {
            if activity.activityType == "pro.aliencat.autocat.addVoiceRecord" {
                ad.quickAction = .addVoiceRecord
            }
            
            if let url = activity.webpageURL {
                if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value {
                    if let jwt = JWT<NumberPayload>(string: token) {
                        ad.quickAction = .openReport(jwt.payload.plateNumber)
                    }
                }
            }
        }
        
        self.window = UIWindow(windowScene: windowScene)
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        
        if Settings.shared.user.token.isEmpty {
            self.window?.rootViewController = storyboard.instantiateViewController(identifier: "AuthController")
        } else {
            self.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController")
        }
        
        self.window?.makeKeyAndVisible()
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.
        
        if let split = self.window?.rootViewController as? MainSplitController, let tabvc = split.viewControllers.first as? UITabBarController {
            if tabvc.selectedIndex == 1 {
                if let nav = tabvc.selectedViewController as? UINavigationController, let child = nav.topViewController {
                    print(type(of: child))
                    if let record = child as? RecordsController {
                        record.stopRecording()
                    }
                }
            }
        }
        
        do {
            try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
        } catch {
            print("sceneDidEnterBackground failed to deactivate audio session: \(error.localizedDescription)")
        }
    }

    func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
        
        if shortcutItem.type == "CheckNumberAction" {
            ad.quickAction = .check
            
            if let split = self.window?.rootViewController as? MainSplitController, let tabvc = split.viewControllers.first as? UITabBarController {
                if tabvc.selectedIndex == 0 {
                    if let nav = tabvc.selectedViewController as? UINavigationController, let child = nav.topViewController {
                        if let check = child as? CheckController {
                            check.handleQuickActions()
                        } else {
                            nav.popToRootViewController(animated: false)
                        }
                    }
                } else {
                    tabvc.selectedIndex = 0
                }
            }
        } else if shortcutItem.type == "AddVoiceRecordAction" {
            self.handleAddVoiceRecordAction()
        }
    }
    
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        if userActivity.activityType == "pro.aliencat.autocat.addVoiceRecord" {
            self.handleAddVoiceRecordAction()
        }
        
        if let url = userActivity.webpageURL {
            if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value {
                if let jwt = JWT<NumberPayload>(string: token) {
                    self.openReport(with: jwt.payload.plateNumber)
                }
            }
        }
    }
    
    func handleAddVoiceRecordAction() {
        guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
        ad.quickAction = .addVoiceRecord
        
        if let split = self.window?.rootViewController as? MainSplitController, let tabvc = split.viewControllers.first as? UITabBarController {
            if tabvc.selectedIndex == 1 {
                if let nav = tabvc.selectedViewController as? UINavigationController, let child = nav.topViewController {
                    if let record = child as? RecordsController {
                        record.handleQuickActions()
                    } else {
                        nav.popToRootViewController(animated: false)
                    }
                }
            } else {
                tabvc.selectedIndex = 1
            }
        }
    }
    
    func openReport(with number: String) {
        guard let rootController = self.window?.rootViewController else { return }
        
        HUD.show(.progress)
        _ = Api.getReport(for: number).observeOn(MainScheduler.instance).subscribe { vehicle in
            let sb = UIStoryboard(name: "Main", bundle: nil)
            let controller = sb.instantiateViewController(identifier: "ReportController") as ReportController
            controller.vehicle = vehicle
            let nav = UINavigationController(rootViewController: controller)
            nav.modalPresentationStyle = .fullScreen
            controller.navigationItem.leftBarButtonItem = BlockBarButtonItem(barButtonSystemItem: .close) { _ in nav.dismiss(animated: true) }
            rootController.present(nav, animated: true)
            HUD.hide()
        } onError: { error in
            HUD.show(error: error)
        }
    }
}

