//
//  PopoverMenuButton.swift
//  Delta
//
//  Created by Riley Testut on 9/2/17.
//  Copyright © 2017 Riley Testut. All rights reserved.
//

import UIKit

extension UINavigationBar
{
    fileprivate var defaultTitleTextAttributes: [NSAttributedString.Key: Any]? {
        if let textAttributes = self._defaultTitleTextAttributes
        {
            return textAttributes
        }
        
        // Make "copy" of self.
        let navigationBar = UINavigationBar(frame: .zero)
        navigationBar.barStyle = self.barStyle
        
        // Set item with title so we can retrieve default text attributes.
        let navigationItem = UINavigationItem(title: "Testut")
        navigationBar.items = [navigationItem]
        navigationBar.isHidden = true
        
        // Must be added to window hierarchy for it to create title UILabel.
        self.addSubview(navigationBar)
        defer { navigationBar.removeFromSuperview() }
        
        navigationBar.layoutIfNeeded()
        
        let textAttributes = navigationBar._defaultTitleTextAttributes
        return textAttributes
    }
    
    private var _defaultTitleTextAttributes: [NSAttributedString.Key: Any]? {
        guard self.titleTextAttributes == nil else { return self.titleTextAttributes }
        
        guard
            let contentView = self.subviews.first(where: { NSStringFromClass(type(of: $0)).contains("ContentView") || NSStringFromClass(type(of: $0)).contains("ItemView") }),
            let titleLabel = contentView.subviews.first(where: { $0 is UILabel }) as? UILabel
        else { return nil }
        
        let textAttributes = titleLabel.attributedText?.attributes(at: 0, effectiveRange: nil)
        return textAttributes
    }
}

class PopoverMenuButton: UIControl
{
    var title: String {
        get { return self.textLabel.text ?? "" }
        set { 
            self.textLabel.text = newValue
            self.updateTextAttributes() 
            self.invalidateIntrinsicContentSize()
        }
    }
    
    private let textLabel: UILabel
    private let arrowLabel: UILabel
    private let stackView: UIStackView
    
    private var parentNavigationBar: UINavigationBar? {
        guard let navigationController = self.parentViewController as? UINavigationController ?? self.parentViewController?.navigationController else { return nil }
        guard self.isDescendant(of: navigationController.navigationBar) else { return nil }
        
        return navigationController.navigationBar
    }
    
    override var intrinsicContentSize: CGSize {
        return self.stackView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    }
    
    init()
    {
        self.textLabel = UILabel()
        self.textLabel.textColor = .black
        
        self.arrowLabel = UILabel()
        self.arrowLabel.text = "▾"
        self.arrowLabel.textColor = .black
        
        self.stackView = UIStackView(arrangedSubviews: [self.textLabel, self.arrowLabel])
        self.stackView.axis = .horizontal
        self.stackView.distribution = .fillProportionally
        self.stackView.alignment = .center
        self.stackView.spacing = 4.0
        self.stackView.isUserInteractionEnabled = false
        
        let intrinsicContentSize = self.stackView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        super.init(frame: CGRect(origin: .zero, size: intrinsicContentSize))
        
        self.addSubview(self.stackView, pinningEdgesWith: .zero)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func didMoveToSuperview()
    {
        self.updateTextAttributes()
    }
}

private extension PopoverMenuButton
{
    func updateTextAttributes()
    {
        guard let parentNavigationBar = self.parentNavigationBar else { return }
        guard let textAttributes = parentNavigationBar.defaultTitleTextAttributes else { return }
        
        for label in [self.textLabel, self.arrowLabel]
        {
            label.attributedText = NSAttributedString(string: label.text ?? "", attributes: textAttributes)
        }
    }
}
