//
//  HeaderBarViewController.swift
//  Astro
//
//  Created by Kerr Miller on 2016-12-05.
//  Copyright © 2016 Mobify Research & Development Inc. All rights reserved.
//

import UIKit

class HeaderBarViewController: UIViewController {
    @objc let navigationBar = UINavigationBar()
    private let navigationBarContainer = UIView()

    // Headerbar stack popping is usually called programmatically from navigation plugin (via popHeaderContent method).
    // However for native back button it is called right away on user interaction and falls into a loop with programmatic pop.
    // We want to suppress this behaviour on user interaction and instead trigger an event that will initiate navigation,
    // which will call pop again but now it'll be considered as “coordinated” with the navigation plugin.
    @objc var navigationBackCoordinated = false

    weak var delegate: HeaderBarViewControllerDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()

        // UINavigationBar and UIToolbar have different .TopAttached behavior.
        //
        // UIToolbar extends its background the amount of the status bar height
        // above its view frame when it's top
        // attached, no matter where it's located in the view hierarchy.
        //
        // UINavigationBar, however, extends its background to the top of its
        // superview. We must therefore wrap our navigation bar in a view that
        // extends the amount of the status bar height above its
        // superview's frame and let the UINavigationBar
        // extend to the top of this view to get the same behavior as UIToolbar.
        //
        //                  +-------------+ ////////////////  } status bar height
        // +--------------+ |             | +--------------+
        // |              | |             | |              |
        // +--------------+ +-------------+ +--------------+
        //        ^                ^                ^
        //    self.view                       navigationBar
        //               navigationBarContainer
        //
        //
        //   self.view > navigationBarContainer > navigationBar

        navigationBar.delegate = self
        navigationBar.sizeToFit()
        navigationBar.translatesAutoresizingMaskIntoConstraints = false

        navigationBarContainer.addSubview(navigationBar)
        navigationBarContainer.sizeToFit()
        navigationBarContainer.translatesAutoresizingMaskIntoConstraints = false
        navigationBarContainer.backgroundColor = navigationBar.barTintColor

        view.addSubview(navigationBarContainer)

        // Note that the amount the status bar overlaps a view is always
        // 20px. This is true even when the 40px tall in-call status bar
        // is shown. In that case the system pushes the root view down
        // 20px to compensate.
        // Note. 20 px is the height for < ios 11. Now it is variable.
        // Don't know if this comment is still true for ios 11+
        // We know just retrieve the status bar height from UIApplication

        let statusBarHeight = UIApplication.shared.statusBarFrame.height
        if #available(iOS 11.0, *) {
            self.additionalSafeAreaInsets = UIEdgeInsets(top: statusBarHeight, left: 0.0, bottom: 0.0, right: 0.0)
        }

        let metrics = ["statusBarHeight": statusBarHeight]

        navigationBar.superview?.addConstraints(
            NSLayoutConstraint.constraints(withVisualFormat: "V:|-statusBarHeight-[navigationBar]|", options: [], metrics: metrics, views: ["navigationBar": navigationBar])
        )
        navigationBar.pinToSuperviewEdgesHorizontally()

        let navigationBarContainerConstraints = [
            NSLayoutConstraint(item: navigationBarContainer,
                               attribute: .top,
                               relatedBy: .equal,
                               toItem: navigationBarContainer.superview,
                               attribute: .top,
                               multiplier: 1,
                               constant: -statusBarHeight),
            NSLayoutConstraint(item: navigationBarContainer,
                               attribute: .bottom,
                               relatedBy: .equal,
                               toItem: navigationBarContainer.superview,
                               attribute: .bottom,
                               multiplier: 1,
                               constant: 0)
        ]
        navigationBarContainer.superview?.addConstraints(navigationBarContainerConstraints)
        navigationBarContainer.pinToSuperviewEdgesHorizontally()
    }
}

// MARK: - UINavigationBarDelegate

extension HeaderBarViewController: UINavigationBarDelegate {

    func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        // Pop Item (navigating back) handler
        if navigationBackCoordinated {
            // Back navigation is called programatically (coordinated with navigation plugin)
            navigationBackCoordinated = false

            // Pop headerbar stack
            return true
        } else {
            // Native back navigation invoked by user interaction with back button
            // Trigger back navigation event
            delegate?.triggerBackEvent()

            //  Do not pop, since not coodinated with navigation plugin
            return false
        }
    }

    func navigationBar(_ navigationBar: UINavigationBar, didPush item: UINavigationItem) {
        navigationBackCoordinated = false
    }

    func position(for bar: UIBarPositioning) -> UIBarPosition {
        return .topAttached
    }
}
