//
//  MVMCoreUISplitViewController+Extension.swift
//  MVMCoreUI
//
//  Created by Scott Pfeil on 6/18/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//

import Foundation

// Navigation bar update functions
public extension MVMCoreUISplitViewController {
    
    /// Convenience function. Sets the navigation and split view properties for the view controller. Panel access is determined if view controller is a detail view protocol.
    static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
        guard let splitView = MVMCoreUISplitViewController.main(),
            navigationController == splitView.navigationController,
            viewController == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() else {
            /// Not the split view navigation controller, skip split functions.
            return
        }
        splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel)
    }
        
    /// Sets the navigation item for the view controller based on the model and splitview controller
    private func set(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
        setLeftPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
        setRightPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
        
        setLeftNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
        setRightNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
        
        setNavigationIconColor(navigationItemModel.tintColor.uiColor)
    }
    
    /// Sets the left navigation items for the view controller based on model and splitview.
    func setLeftNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) {
        guard let topViewController = navigationController.topViewController else { return }

        var leftItems: [UIBarButtonItem] = []
        let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject

        // Add back button first.
        if navigationItemModel?.hidesSystemBackButton == true {
            var showBackButton: Bool
            if let forceBackButton = navigationItemModel?.alwaysShowBackButton {
                showBackButton = forceBackButton
            } else {
                showBackButton = MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 0 > 1
            }
            if showBackButton {
                if let backButtonModel = navigationItemModel?.backButton {
                    leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
                } else if let backButton = backButton {
                    // Default to legacy if we have default back button.
                    leftItems.append(backButton)
                }
            }
        }
        
        // Add the panel button after the back button.
        if let panelButton = leftPanelButton,
            leftPanelIsAccessible,
            !leftPanelStaysExtended() {
            leftItems.append(panelButton)
        }
        
        // Add other model buttons
        if let leftItemModels = navigationItemModel?.additionalLeftButtons {
            for item in leftItemModels {
                leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
            }
        }
        
        // Add any buttons added by the splitview.
        if let additionalLeftButtons = additionalLeftButtons(for: viewController) {
            leftItems.append(contentsOf: additionalLeftButtons)
        }
        
        topViewController.navigationItem.setLeftBarButtonItems(leftItems.count > 0 ? leftItems : nil, animated: !DisableAnimations.boolValue)
    }
    
    /// Sets the right navigation items for the view controller based on model and splitview.
    func setRightNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) {
        guard let topViewController = navigationController.topViewController else { return }

        let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
        var rightItems: [UIBarButtonItem] = []
        
        // Add the panel button first.
        if let panelButton = rightPanelButton,
            rightPanelIsAccessible,
            !rightPanelStaysExtended() {
            rightItems.append(panelButton)
        }
        
        // Add other model buttons
        if let rightItemModels = navigationItemModel?.additionalRightButtons {
            for item in rightItemModels {
                rightItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
            }
        }
        
        // Add any buttons added by the splitview.
        if let additionalRightButtons = additionalRightButtons(for: viewController) {
            rightItems.append(contentsOf: additionalRightButtons)
        }
        
        topViewController.navigationItem.setRightBarButtonItems(rightItems.count > 0 ? rightItems : nil, animated: !DisableAnimations.boolValue)
    }
    
    @objc func navigationBarModelExists() -> Bool {
        // Legacy Navigation
        guard let currentViewController = getCurrentDetailViewController(),
              let _ = navigationController?.getNavigationModel(from: currentViewController) else { return false }
        return true
    }
    
    /// Convenience function to update the navigation bar if the controller is the current lowest controller.
    @objc func updateNavigationBarFor(viewController: UIViewController) {
        guard let navigationController = navigationController,
              navigationController.isDisplayed(viewController: viewController),
              let model = navigationController.getNavigationModel(from: viewController) else { return }
        set(for: viewController, navigationController: navigationController, navigationItemModel: model)
    }
}

extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol {
    public func getCurrentViewController() -> UIViewController? {
        navigationController?.getCurrentViewController()
    }
    
    public func containsPage(withPageType pageType: String?) -> Bool {
        navigationController?.containsPage(withPageType: pageType) ?? false
    }
    
    public func displayedViewController(_ viewController: UIViewController) {
        setupPanels()
        updateNavigationBarFor(viewController: viewController)
    }
    
    public func newDataReceived(in viewController: UIViewController) {
        updateNavigationBarFor(viewController: viewController)
    }
}
