//
//  UserActivityHandlingContext.swift
//  Tusker
//
//  Created by Shadowfacts on 2/25/23.
//  Copyright © 2023 Shadowfacts. All rights reserved.
//

import UIKit
import Duckable
import ComposeUI

@MainActor
protocol UserActivityHandlingContext {
    var isHandoff: Bool { get }
    
    func select(route: TuskerRoute)
    func present(_ vc: UIViewController)
    
    var topViewController: UIViewController? { get }
    func popToRoot()
    func push(_ vc: UIViewController)
    
    func compose(editing draft: Draft)
    
    func finalize(activity: NSUserActivity)
}

struct ActiveAccountUserActivityHandlingContext: UserActivityHandlingContext {
    let isHandoff: Bool
    let root: TuskerRootViewController
    var navigationDelegate: TuskerNavigationDelegate {
        root.getNavigationDelegate()!
    }
    
    func select(route: TuskerRoute) {
        root.select(route: route, animated: true)
    }
    
    func present(_ vc: UIViewController) {
        navigationDelegate.present(vc, animated: true)
    }
    
    var topViewController: UIViewController? { root.getNavigationController().topViewController }
    
    func popToRoot() {
        _ = root.getNavigationController().popToRootViewController(animated: true)
    }
    
    func push(_ vc: UIViewController) {
        navigationDelegate.show(vc, sender: nil)
    }
    
    func compose(editing draft: Draft) {
        navigationDelegate.compose(editing: draft, animated: true, isDucked: true)
    }
    
    func finalize(activity: NSUserActivity) {
    }
}

class StateRestorationUserActivityHandlingContext: UserActivityHandlingContext {
    private var state = State.initial
    let root: TuskerRootViewController
    
    init(root: TuskerRootViewController) {
        self.root = root
    }
    
    var isHandoff: Bool { false }
    
    func select(route: TuskerRoute) {
        root.select(route: route, animated: false)
        state = .selectedRoute
    }
    
    var topViewController: UIViewController? { root.getNavigationController().topViewController }
    
    func popToRoot() {
        // unnecessary during state restoration
    }
    
    func push(_ vc: UIViewController) {
        precondition(state >= .selectedRoute)
        root.getNavigationController().pushViewController(vc, animated: false)
        state = .pushed
    }
    
    func present(_ vc: UIViewController) {
        root.present(vc, animated: false)
        state = .presented
    }
    
    func compose(editing draft: Draft) {
        if #available(iOS 16.0, *),
           UIDevice.current.userInterfaceIdiom == .phone {
            self.root.compose(editing: draft, animated: false, isDucked: true)
        } else {
            DispatchQueue.main.async {
                self.root.compose(editing: draft, animated: true, isDucked: false)
            }
        }
        state = .presented
    }
    
    func finalize(activity: NSUserActivity) {
        precondition(state > .initial)
        if #available(iOS 16.0, *),
           let duckedDraft = UserActivityManager.getDuckedDraft(from: activity) {
            self.root.compose(editing: duckedDraft, animated: false, isDucked: true)
        }
    }
    
    enum State: Comparable {
        case initial
        case selectedRoute
        case pushed
        case presented
    }
}
