//
//  CollectionViewCell.swift
//  MVMCoreUI
//
//  Created by Scott Pfeil on 4/6/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//

import Foundation


/// A base collection view cell with basic mvm functionality.
open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCoreViewProtocol, CollectionTemplateItemProtocol, MFButtonProtocol {
    //--------------------------------------------------
    // MARK: - Properties
    //--------------------------------------------------
    
    // Convenience helpers
    open var molecule: MoleculeViewProtocol?
    public let containerHelper = ContainerHelper()
    open var model: CollectionItemModelProtocol?
    
    /// The width, used for establishing columns
    open var width: CGFloat?
    
    private var initialSetupPerformed = false
    
    // MARK: - Inits
    public override init(frame: CGRect) {
        super.init(frame: .zero)
        initialSetup()
    }
    
    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialSetup()
    }
    
    private func initialSetup() {
        if !initialSetupPerformed {
            initialSetupPerformed = true
            setupView()
        }
    }
    
    // MARK: - Helpers

    /// Convenience function. Adds a molecule to the view.
    open func addMolecule(_ molecule: MoleculeViewProtocol) {
        contentView.addSubview(molecule)
        containerHelper.constrainView(molecule)
        self.molecule = molecule
    }
    
    // MARK: - MVMCoreViewProtocol
    open func setupView() {
        isAccessibilityElement = false
        contentView.isAccessibilityElement = false
        insetsLayoutMarginsFromSafeArea = false
        contentView.insetsLayoutMarginsFromSafeArea = false
        contentView.preservesSuperviewLayoutMargins = false
        MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0)
    }
    
    open func updateView(_ size: CGFloat) {
        if let model = model as? ContainerModelProtocol {
            containerHelper.updateViewMargins(contentView, model: model, size: size)
        }
        (molecule as? MVMCoreViewProtocol)?.updateView(size)
    }
    
    // MARK: - MoleculeViewProtocol
    open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
        guard let model = model as? CollectionItemModelProtocol else { return }
        self.model = model
        
        if let moleculeModel = model as? MoleculeModelProtocol,
            let backgroundColor = moleculeModel.backgroundColor {
            self.backgroundColor = backgroundColor.uiColor
        }
        
        // align if needed.
        if let model = model as? ContainerModelProtocol {
            containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
        }
    }
    
    open func reset() {
        molecule?.reset()
        backgroundColor = .clear
        width = nil
    }
    
    // MARK: Overridables
    // Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
    
    open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
         return model.moleculeName
    }

    open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
        return nil
    }
    
    open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
        return nil
    }
    
    //--------------------------------------------------
    // MARK: - CollectionTemplateItemProtocol
    //--------------------------------------------------
    
    public func set(width: CGFloat) {
        self.width = width
    }
    
    // MARK: - Override
    
    open func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool {
        if let action = model?.action {
            Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData)
        }
        return false
    }
    
    open func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {}
    
    // Column logic, set width.
    override open func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
        let autoLayoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)
        guard let width = width else { return autoLayoutAttributes }
        
        let targetSize = CGSize(width: width, height: 0)
        let newSize = contentView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .defaultLow)
        let newFrame = CGRect(origin: autoLayoutAttributes.frame.origin, size: newSize)
        autoLayoutAttributes.frame = newFrame
        return autoLayoutAttributes
    }
}
