//
//  UINavigationController+Extension.swift
//  MVMCoreUI
//
//  Created by Scott Pfeil on 3/14/22.
//  Copyright © 2022 Verizon Wireless. All rights reserved.
//

import Foundation
import MVMCore

public extension UINavigationController {
    
    /// Convenience function for setting the navigation item.
    @MainActor
    func setNavigationItem(with model: NavigationItemModelProtocol, for viewController: UIViewController, coordinatingWith pageBehaviorController: PageBehaviorHandlerProtocol? = nil) {
        
        let behaviorHandler = pageBehaviorController ?? viewController as? PageBehaviorHandlerProtocol;
        
        behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
            behavior.willSetupNavigationBar(with: model, updating: navigationBar)
        }
        
        viewController.navigationItem.title = model.title
        viewController.navigationItem.accessibilityLabel = model.title
        viewController.navigationItem.hidesBackButton = model.hidesSystemBackButton
        viewController.navigationItem.leftItemsSupplementBackButton = !model.hidesSystemBackButton
        setNavigationButtons(with: model, for: viewController)
        setNavigationTitleView(with: model, for: viewController, coordinatingWith: pageBehaviorController)
        
        behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
            behavior.didSetupNavigationBar(view: navigationBar, with: model)
        }
    }
    
    /// Convenience function for setting the navigation buttons.
    @MainActor
    func setNavigationButtons(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
        let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
        var leftItems: [UIBarButtonItem] = []
        if model.hidesSystemBackButton,
           model.alwaysShowBackButton != false {
            if let backButtonModel = model.backButton,
               NavigationHandler.shared().getViewControllers(for: self).count > 1 || model.alwaysShowBackButton ?? false {
                leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
            }
            if let leftItemModels = model.additionalLeftButtons {
                for item in leftItemModels {
                    leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
                }
            }
        }
        viewController.navigationItem.leftBarButtonItems = leftItems.count > 0 ? leftItems : nil

        var rightItems: [UIBarButtonItem] = []
        if let rightItemModels = model.additionalRightButtons {
            for item in rightItemModels {
                rightItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
            }
        }
        viewController.navigationItem.rightBarButtonItems = rightItems.count > 0 ? rightItems : nil
    }
    
    /// Convenience function for setting the navigation titleView.
    @MainActor
    func setNavigationTitleView(with model: NavigationItemModelProtocol, for viewController: UIViewController, coordinatingWith pageBehaviorController: PageBehaviorHandlerProtocol? = nil) {
        guard let titleViewModel = model.titleView else { return }
        
        let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
        
        let behaviorHandler = pageBehaviorController ?? viewController as? PageBehaviorHandlerProtocol;
        behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
            behavior.willSetupMolecule(with: titleViewModel, updating: nil)
        }
        
        guard let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) else { return }
        
        viewController.navigationItem.titleView = molecule
        
        behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
            behavior.didSetupMolecule(view: molecule, withModel: titleViewModel)
        }
    }
    
    /// Convenience function for setting the navigation bar ui
    @MainActor
    func setNavigationBarUI(with model: NavigationItemModelProtocol) {
        let navigationBar = navigationBar
        let font = Styler.Font.BoldTitleSmall.getFont(false)
        let backgroundColor = model.backgroundColor?.uiColor
        let tint = model.tintColor.uiColor
        navigationBar.tintColor = tint

        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.titleTextAttributes = [NSAttributedString.Key.font: font,
                                          NSAttributedString.Key.foregroundColor: tint];
        appearance.backgroundColor = backgroundColor
        appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor)
        appearance.titlePositionAdjustment = model.titleOffset ?? .zero
        appearance.setShadow(for: model.line)
        navigationBar.standardAppearance = appearance
        navigationBar.scrollEdgeAppearance = appearance
        
        setNavigationBarHidden(model.hidden, animated: false)
    }
    
    @objc @MainActor
    func getViewController() -> UIViewController? {
        guard let topViewController = getViewControllers().last,
              let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else { return nil }
        return viewController
    }
}

public extension UINavigationBarAppearance {
    func setShadow(for model: LineModel?) {
        let model = model ?? LineModel(type: .secondary)
        let line = Line(model: model, nil, nil)
        if line.shouldBeVisible() {
           shadowColor = line.lineColor
        } else {
           shadowColor = .clear
        }
        shadowImage = line.lineColor.image(CGSize(width: line.lineWidth, height: line.lineWidth)).withRenderingMode(.alwaysTemplate)
    }
}
