//
//  PillButton.swift
//  MVMCoreUI
//
//  Created by Scott Pfeil on 1/28/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//

import UIKit
import VDSColorTokens
import VDS
import MVMCore
import Combine

open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol, VDSMoleculeViewProtocol {
        
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    
    open var viewModel: ButtonModel!
    public var delegateObject: MVMCoreUIDelegateObject?
    public var additionalData: [AnyHashable: Any]?

    internal var onClickCancellable: Cancellable?
    
    //--------------------------------------------------
    // MARK: - VDSMoleculeViewProtocol
    //--------------------------------------------------
    
    open func viewModelDidUpdate() {
        if let accessibilityIdentifier = viewModel.accessibilityIdentifier {
            self.accessibilityIdentifier = accessibilityIdentifier
        }
        
        text = viewModel.title
        isEnabled = viewModel.enabled
        size = viewModel.size
        use = viewModel.style ?? .primary
        surface = viewModel.inverted ? .dark : .light
        if let accessibilityText = viewModel.accessibilityText {
            accessibilityLabel = accessibilityText
        }

        accessibilityTraits = isEnabled ? (viewModel?.accessibilityTraits ?? .button) : (viewModel?.disabledAccessibilityTraits ?? .none)
    
        set(with: viewModel.action, delegateObject: delegateObject, additionalData: additionalData)
        
        viewModel.updateUI = { [weak self] in
            MVMCoreDispatchUtility.performBlock(onMainThread: {
                guard let self = self else { return }
                self.isEnabled = self.viewModel.enabled
            })
        }
        
        FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
    }
    
    //--------------------------------------------------
    // MARK: - MVMCoreViewProtocol
    //--------------------------------------------------
    

    open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject:  MVMCoreUIDelegateObject?) -> CGFloat? {
        return (model as? ButtonModel)?.size.height

    }
    
    open func updateView(_ size: CGFloat) {}
    
    open override func setup() {
        super.setup()
        setupView()
    }
    
    open func setupView() {}
    
    //--------------------------------------------------
    // MARK: - MVMCoreUIViewConstrainingProtocol
    //--------------------------------------------------
    
    open func horizontalAlignment() -> UIStackView.Alignment { .center }
    
    //--------------------------------------------------
    // MARK: - Action
    //--------------------------------------------------
    
    open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
        onClick = { [weak self] control in
            guard let self = self, let viewModel = self.viewModel else { return }
            Task(priority: .userInitiated) {
                try await Self.performButtonAction(with: viewModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: viewModel)
            }
        }
    }
    
    open class func performButtonAction(with model: ActionModelProtocol, button: MFButtonProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, sourceModel: MoleculeModelProtocol? = nil) async throws {
        guard delegateObject?.buttonDelegate?.button?(button, shouldPerformActionWithMap: model.toJSON(), additionalData: additionalData) ?? true else { return }
        try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: model, additionalData: MVMCoreUIActionHandler.add(sourceModel: sourceModel, to: additionalData), delegateObject: delegateObject)
    }
}
