//
//  MenuPicker.swift
//  TuskerComponents
//
//  Created by Shadowfacts on 11/7/22.
//  Copyright © 2022 Shadowfacts. All rights reserved.
//

import SwiftUI

public struct MenuPicker<Value: Hashable>: UIViewRepresentable {
    public typealias UIViewType = UIButton
    
    @Binding var selection: Value
    let options: [Option]
    var buttonStyle: ButtonStyle
    
    private var selectedOption: Option {
        options.first(where: { $0.value == selection })!
    }
    
    public init(selection: Binding<Value>, options: [Option], buttonStyle: ButtonStyle = .labelAndIcon) {
        self._selection = selection
        self.options = options
        self.buttonStyle = buttonStyle
    }
    
    public func makeUIView(context: Context) -> UIButton {
        let button = UIButton()
        button.showsMenuAsPrimaryAction = true
        button.setContentHuggingPriority(.required, for: .horizontal)
        return button
    }
    
    public func updateUIView(_ button: UIButton, context: Context) {
        var config = UIButton.Configuration.borderless()
        if #available(iOS 16.0, *) {
            config.indicator = .popup
        }
        if buttonStyle.hasIcon {
            config.image = selectedOption.image
        }
        if buttonStyle.hasLabel {
            config.title = selectedOption.title
        }
        button.configuration = config
        button.menu = UIMenu(children: options.map { opt in
            let action = UIAction(title: opt.title, subtitle: opt.subtitle, image: opt.image, state: opt.value == selection ? .on : .off) { _ in
                selection = opt.value
            }
            action.accessibilityLabel = opt.accessibilityLabel
            return action
        })
        button.accessibilityLabel = selectedOption.accessibilityLabel ?? selectedOption.title
        button.isPointerInteractionEnabled = buttonStyle == .iconOnly
    }
    
    public struct Option {
        public let value: Value
        public let title: String
        public let subtitle: String?
        public let image: UIImage?
        public let accessibilityLabel: String?
        
        public init(value: Value, title: String, subtitle: String? = nil, image: UIImage? = nil, accessibilityLabel: String? = nil) {
            self.value = value
            self.title = title
            self.subtitle = subtitle
            self.image = image
            self.accessibilityLabel = accessibilityLabel
        }
    }
    
    public enum ButtonStyle {
        case labelAndIcon, labelOnly, iconOnly
        
        var hasLabel: Bool {
            switch self {
            case .labelAndIcon, .labelOnly:
                return true
            default:
                return false
            }
        }
        
        var hasIcon: Bool {
            switch self {
            case .labelAndIcon, .iconOnly:
                return true
            default:
                return false
            }
        }
    }
}

struct MenuPicker_Previews: PreviewProvider {
    @State static var value = 0
    static var previews: some View {
        MenuPicker(selection: $value, options: [
            .init(value: 0, title: "Zero"),
            .init(value: 1, title: "One"),
            .init(value: 2, title: "Two"),
        ])
    }
}
