//
//  PickerBase.swift
//  VDSSample
//
//  Created by Matt Bruce on 8/1/22.
//

import Foundation
import UIKit
import VDS
import Combine

public struct PickerType : RawRepresentable, Equatable, Hashable {
    public var rawValue: String
    public init(_ rawValue: String) {
        self.rawValue = rawValue
    }
    public init(rawValue: String) {
        self.rawValue = rawValue
    }
    
    public static var surface = PickerType(rawValue: "surface")
    public static var textPosition = PickerType(rawValue: "textPosition")
    public static var textSize = PickerType(rawValue: "textSize")
    public static var fontCategory = PickerType(rawValue: "fontCategory")
}

public protocol PickerViewable: UIPickerViewDataSource, UIPickerViewDelegate, Hashable {
    associatedtype EnumType: RawRepresentable
    var items: [EnumType] { get set }
    var onPickerDidSelect: ((EnumType) -> Void)? { get set }
    var scrollToBottom: (()->Void)? { get set }
}

public class PickerSelectorView<EnumType: RawRepresentable>: UIStackView, PickerViewable {
    private weak var picker: UIPickerView?
    fileprivate var selectedIndex = 0
    private var subscribers = Set<AnyCancellable>()
    private var label = Label().with {
        $0.textStyle = .bodyLarge
    }

    public var selectedItem: EnumType {
        return items[selectedIndex]
    }
    
    private var button = Button().with { instance in
        instance.size = .small
        instance.use = .secondary
        instance.text = "Select"
    }
    
    public var text: String = "" {
        didSet {
            label.text = text
            updateSelectedIndex()
        }
    }
    
    public var items: [EnumType] {
        didSet { selectedIndex = 0 }
    }
    public var onClick: AnyCancellable?
    public var onPickerDidSelect: ((EnumType) -> Void)?
    public var scrollToBottom: (()->Void)?
    public init(title: String, picker: UIPickerView? = nil, items: [EnumType]) {
        self.picker = picker
        self.items = items
        super.init(frame: .zero)
        
        self.axis = .horizontal
        self.distribution = .fillEqually
        self.alignment = .fill
        text = title
        label.text = title
        updateSelectedIndex()
        addArrangedSubview(label)
        addArrangedSubview(.makeWrapper(for: button, isTrailing: false))
        button.onClick = { [weak self] _ in
            self?.picker?.delegate = self
            self?.picker?.dataSource = self
            self?.picker?.reloadAllComponents()
            self?.picker?.selectRow(self?.selectedIndex ?? 0, inComponent: 0, animated: false)
            self?.picker?.isHidden = false
            self?.scrollToBottom?()
        }
    }
    
    func updateSelectedIndex() {
        guard let foundTextIndex = items.firstIndex(where: { "\($0.rawValue)" == text }) else { return }
        selectedIndex = foundTextIndex //add one since we always have a empty space
    }
    
    public required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
        1
    }
    
    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        items.count
    }
    
    public func pickerView( _ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        selectedIndex = row
        onPickerDidSelect?(items[row])
        text = "\(items[row].rawValue)"
        pickerView.isHidden = true
    }
    
    public func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
        var label = UILabel()
        if let v = view as? UILabel { label = v }
        label.font = TextStyle.titleMedium.font
        label.text = title(for: row)
        label.textAlignment = .center
        return label
    }
    
    public func set(item: EnumType) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.001) { [weak self] in
            guard let self else { return }
            self.text = "\(item.rawValue)"
        }
    }
    
    private func title(for row: Int) -> String {
        guard  let item = items[row].rawValue as? String else { return "" }
        return item
    }

}

public class SurfacePickerSelectorView: PickerSelectorView<Surface>{
    init(picker: UIPickerView? = nil){
        super.init(title: "light", picker: picker, items: [.light, .dark])
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

public class TextPositionPickerSelectorView: PickerSelectorView<TextPosition>{
    init(picker: UIPickerView? = nil){
        super.init(title: "left", picker: picker, items: [.left, .right])
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

public class TextSizePickerSelectorView: PickerSelectorView<TextStyle.FontSize>{
    init(title: String, picker: UIPickerView? = nil){
        super.init(title: title, picker: picker, items: [.small, .large])
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

public class FontCategoryPickerSelectorView: PickerSelectorView<TextStyle.FontCategory>{
    init(title: String, picker: UIPickerView? = nil){
        super.init(title: title, picker: picker, items: TextStyle.FontCategory.allCases)
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
