//
//  ComposeSceneDelegate.swift
//  Tusker
//
//  Created by Shadowfacts on 12/12/20.
//  Copyright © 2020 Shadowfacts. All rights reserved.
//

import UIKit
import Combine
import UserAccounts
import ComposeUI

class ComposeSceneDelegate: UIResponder, UIWindowSceneDelegate, TuskerSceneDelegate {

    var window: UIWindow?
    
    var rootViewController: TuskerRootViewController? { nil }
    
    private var cancellables = Set<AnyCancellable>()
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = scene as? UIWindowScene else {
            return
        }
        
        guard UserAccountsManager.shared.onboardingComplete else {
            UIApplication.shared.requestSceneSessionDestruction(session, options: nil, errorHandler: nil)
            return
        }
        
        let account: UserAccountInfo
        let controller: MastodonController
        let draft: Draft?
        
        if let activity = connectionOptions.userActivities.first ?? session.stateRestorationActivity {
            if let activityAccount = UserActivityManager.getAccount(from: activity) {
                account = activityAccount
            } else {
                // todo: this potentially changes the account for the draft, should show the same warning to user as in the drafts selection screen
                account = UserAccountsManager.shared.getMostRecentAccount()!
            }
            
            controller = MastodonController.getForAccount(account)
            
            if let activityDraft = UserActivityManager.getDraft(from: activity) {
                draft = activityDraft
            } else if let mentioning = activity.userInfo?["mentioning"] as? String {
                draft = controller.createDraft(inReplyToID: nil, mentioningAcct: mentioning)
            } else {
                draft = nil
            }
        } else {
            account = UserAccountsManager.shared.getMostRecentAccount()!
            controller = MastodonController.getForAccount(account)
            draft = nil
        }
        
        session.mastodonController = controller
        controller.initialize()
        
        let composeVC = ComposeHostingController(draft: draft, mastodonController: controller)
        composeVC.delegate = self
        
        window = UIWindow(windowScene: windowScene)
        window!.rootViewController = composeVC
        window!.makeKeyAndVisible()
        
        updateTitle(draft: composeVC.controller.draft)
        composeVC.controller.$draft
            .sink { [unowned self] in self.updateTitle(draft: $0) }
            .store(in: &cancellables)
        
        NotificationCenter.default.addObserver(self, selector: #selector(themePrefChanged), name: .themePreferenceChanged, object: nil)
        themePrefChanged()
    }
    
    func sceneWillResignActive(_ scene: UIScene) {
        DraftsPersistentContainer.shared.save()
        
        if let window = window,
           let nav = window.rootViewController as? UINavigationController,
           let compose = nav.topViewController as? ComposeHostingController,
           !compose.controller.didPostSuccessfully {
            scene.userActivity = UserActivityManager.editDraftActivity(id: compose.controller.draft.id, accountID: scene.session.mastodonController!.accountInfo!.id)
        }
    }
    
    func stateRestorationActivity(for scene: UIScene) -> NSUserActivity? {
        return scene.userActivity
    }
    
    private func updateTitle(draft: Draft) {
        // Don't set the scene title on macOS since it shows both that and the VC title in the window titlebar
        #if !targetEnvironment(macCatalyst)
        guard !ProcessInfo.processInfo.isiOSAppOnMac,
            let scene = window?.windowScene,
              let mastodonController = scene.session.mastodonController else {
            return
        }
        if let inReplyToID = draft.inReplyToID,
           let inReplyTo = mastodonController.persistentContainer.status(for: inReplyToID) {
            scene.title = "Reply to @\(inReplyTo.account.acct)"
        } else {
            scene.title = "New Post"
        }
        #endif
    }
    
    @objc private func themePrefChanged() {
        applyAppearancePreferences()
    }
    
}

extension ComposeSceneDelegate: ComposeHostingControllerDelegate {
    func dismissCompose(mode: DismissMode) -> Bool {
        let animation: UIWindowScene.DismissalAnimation
        switch mode {
        case .cancel:
            animation = .decline
        case .post:
            animation = .commit
        }
        closeWindow(animation: animation)
        return true
    }
}
