//
//  TileContainer.swift
//  MVMCoreUI
//
//  Created by Matt Bruce on 4/15/24.
//  Copyright © 2024 Verizon Wireless. All rights reserved.
//

import Foundation
import VDS
import Combine

open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    
    public var model: MoleculeModelProtocol?
    
    public var viewModel: TileContainerModel!
    public var delegateObject: MVMCoreUIDelegateObject?
    public var additionalData: [AnyHashable: Any]?
        
    public var molecule: MoleculeViewProtocol? {
        willSet {
            if newValue == nil {
                molecule?.removeFromSuperview()
            }
        }
    }
    
    //--------------------------------------------------
    // MARK: - Initializers
    //--------------------------------------------------
    public convenience required init() {
        self.init(frame: .zero)
    }
    
    //--------------------------------------------------
    // MARK: - Public
    //--------------------------------------------------
    public func viewModelDidUpdate() {
        
        if let moleculeModel = viewModel.molecule {
            if let molecule,
                moleculeModel.moleculeName == molecule.model?.moleculeName {
                molecule.set(with: moleculeModel, delegateObject, additionalData)
            } else if let moleculeView = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) {
                molecule = moleculeView
                addContentView(moleculeView)
            }
        }
    
        // set backgroundImage
        if let imageName = viewModel.backgroundImage {
            loadImage(imageName)
        }
        
        //set action
        if let action = viewModel.action {
            //add the subscriber
            onClick = { [weak self] control in
                guard let self, let viewModel = self.viewModel else { return }
                MVMCoreUIActionHandler.performActionUnstructured(with: action,
                                                                 sourceModel: viewModel,
                                                                 additionalData: self.additionalData,
                                                                 delegateObject: self.delegateObject)
            }
        }
        
        //set the rest of the properties
        surface = viewModel.surface
        imageFallbackColor = viewModel.imageFallbackColor
        width = viewModel.width
        height = viewModel.height
        showBorder = viewModel.showBorder
        showDropShadow = viewModel.showDropShadow
        padding = viewModel.padding
        color = viewModel.color
        aspectRatio = viewModel.aspectRatio
        backgroundEffect = viewModel.backgroundEffect
    }
    
    private func loadImage(_ imageName: String? = nil) {
        guard let imageName else {
            if backgroundImage != nil {
                backgroundImage = nil
            }
            return
        }
        
        let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
            guard let self = self else { return }
            self.backgroundImage = image
        })}
        MVMCoreCache.shared()?.getImage(imageName, useWidth: false, widthForS7: 0, useHeight: false, heightForS7: 0, format: nil, localFallbackImageName: nil, allowServerQueryParameters: false, localBundle: nil, completionHandler: finishedLoadingBlock)
    }

    //--------------------------------------------------
    // MARK: - MVMCoreViewProtocol
    //--------------------------------------------------
    open func updateView(_ size: CGFloat) {}

    //--------------------------------------------------
    // MARK: - MoleculeViewProtocol
    //--------------------------------------------------
    //since this is a class func, we can't reference it directly
    public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
        100
    }
    
    /// Allows the molecule to set its name for reuse. Default could be moleculeName. Mainly used for list or collections.
    public static func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
        // This will aggregate names of molecules to make an id.
        guard let containerModel = model as? TileContainerModel,
              let molecule = containerModel.molecule,
              let moleculeClass = ModelRegistry.getMoleculeClass(molecule),
              let moleculeName = moleculeClass.nameForReuse(with: molecule, delegateObject)
        else { return "\(model.moleculeName)<>" }
        
        return "\(model.moleculeName)<\(moleculeName)>"
    }

    //--------------------------------------------------
    // MARK: - Overrides
    //--------------------------------------------------
    open override func layoutSubviews() {
        super.layoutSubviews()
        // Accounts for any collection size changes
        DispatchQueue.main.async { [weak self] in
            guard let self else { return }
            self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
        }
    }
}

extension TileContainer: MVMCoreUIViewConstrainingProtocol {
    public func horizontalAlignment() -> UIStackView.Alignment { .leading }
}
