//
//  ToolbarView.swift
//  App
//
//  Created by James Magahern on 8/14/20.
//

import UIKit

class ToolbarView: UIView
{
    var urlBar: URLBar? {
        didSet {
            guard let urlBar else { return }
            containerView.addSubview(urlBar)
            
            urlBar.textField.addAction(.init(handler: { [unowned self] _ in
                layoutLatch.activate()
            }), for: [ .editingDidBegin, .editingDidEnd ])
        }
    }
    
    var cancelButtonVisible: Bool = false { didSet { setNeedsLayout() } }
    
    let containerView = UIView(frame: .zero)
    let backgroundView = GradientView(direction: .vertical, colors: [
        .secondarySystemGroupedBackground,
        .secondarySystemGroupedBackground
    ])
    let cancelButton = UIButton(type: .system)
    
    let leadingButtonsView = ToolbarButtonContainerView(frame: .zero)
    let trailingButtonsView = ToolbarButtonContainerView(frame: .zero)
    
    // Something I'm sure I'll regret: to ensure animation with the keyboard, latch layout until we get the right signal.
    lazy var layoutLatch = LayoutLatch(self)
    
    convenience init()
    {
        self.init(frame: .zero)
        addSubview(backgroundView)
        addSubview(containerView)
        
        containerView.addSubview(leadingButtonsView)
        containerView.addSubview(trailingButtonsView)
        
        cancelButton.setTitle("Cancel", for: .normal)
        containerView.addSubview(cancelButton)
        
        layer.masksToBounds = false
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOpacity = 0.3
        layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
        layer.shadowRadius = 1.8
    }
    
    override func sizeThatFits(_ size: CGSize) -> CGSize
    {
        var height: CGFloat = 42.0
        if traitCollection.userInterfaceIdiom == .mac {
            height = 40.0
        }
        
        return CGSize(width: size.width, height: height)
    }
    
    override func layoutSubviews()
    {
        guard !layoutLatch.latched else { return }
        super.layoutSubviews()
        
        let shadowPath = UIBezierPath(rect: bounds)
        layer.shadowPath = shadowPath.cgPath

        backgroundView.frame = bounds
        
        var containerBounds = bounds
        containerBounds.size.height -= safeAreaInsets.bottom
        containerView.frame = containerBounds
        containerView.frame = containerView.frame.insetBy(dx: 8.0, dy: 4.0)
        
        let buttonContainerInset = UIEdgeInsets(top: 1.0, left: 0.0, bottom: 1.0, right: 0.0)
        
        let urlBarPadding = CGFloat(8.0)
        var urlBarInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
        
        // Cancel button
        var cancelButtonSize = cancelButton.sizeThatFits(containerView.bounds.size)
        cancelButtonSize.width += (urlBarPadding * 2)
        cancelButton.frame = CGRect(origin: CGPoint(x: (containerView.bounds.maxX - cancelButtonSize.width), y: 0),
                                    size: CGSize(width: cancelButtonSize.width + urlBarPadding, height: containerView.bounds.height))
        
        // Leading toolbar buttons
        if leadingButtonsView.numberOfButtonViews > 0 {
            let leadingContainerSize = leadingButtonsView.sizeThatFits(containerView.bounds.size)
            leadingButtonsView.frame = CGRect(origin: .zero, size: leadingContainerSize).inset(by: buttonContainerInset)
            urlBarInsets.left = urlBarPadding
        } else {
            leadingButtonsView.frame = .zero
        }
        
        // Trailing toolbar buttons
        let trailingContainerSize = trailingButtonsView.sizeThatFits(containerView.bounds.size)
        trailingButtonsView.frame = CGRect(origin: CGPoint(x: (containerView.bounds.maxX - trailingContainerSize.width), y: 0), size: trailingContainerSize)
        trailingButtonsView.frame = trailingButtonsView.frame.inset(by: buttonContainerInset)
        urlBarInsets.right = urlBarPadding
        
        var avoidingSize: CGSize = .zero
        if cancelButtonVisible {
            cancelButton.alpha = 1.0
            trailingButtonsView.alpha = 0.0
            
            avoidingSize = cancelButtonSize
        } else {
            cancelButton.alpha = 0.0
            trailingButtonsView.alpha = 1.0
            
            avoidingSize = trailingContainerSize
        }
        
        if let urlBar = urlBar {
            var origin = CGPoint(
                x: leadingButtonsView.frame.maxX,
                y: 0.0
            )
            
            if origin.x == 0 {
                // Add some padding if url bar is flush with side
                origin.x = layoutMargins.left
            }
            
            urlBar.frame = CGRect(
                origin: origin,
                size: CGSize(
                    width: containerView.bounds.width - avoidingSize.width - origin.x,
                    height: trailingContainerSize.height
                )
            )
            
            urlBar.frame = urlBar.frame.inset(by: urlBarInsets).inset(by: buttonContainerInset)
        }
    }
}

