//
//  ListStoreLocator.swift
//  MVMCoreUI
//
//  Created by Lekshmi S on 12/10/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//

@objcMembers open class ListStoreLocator: TableViewCell {
    //--------------------------------------------------
    // MARK: - Outlets
    //--------------------------------------------------
    
    public let heart = Heart()
    public let leftHeadline = Label(fontStyle: .BoldBodySmall)
    public let leftBody = Label(fontStyle: .RegularBodySmall)
    public let leftSubBody = Label(fontStyle: .RegularBodySmall)
    public let rightLabel = Label(fontStyle: .RegularBodySmall)
    private lazy var rightLabelStackItem: StackItem = {
        StackItem(andContain: rightLabel)
    }()
    
    public lazy var horizontalStack: Stack<StackModel> = {
        return Stack<StackModel>(with: StackModel(molecules: [StackItemModel(horizontalAlignment: .fill),
                                                              StackItemModel(horizontalAlignment: .fill),
                                                              StackItemModel(horizontalAlignment: .trailing)],
                                                  axis: .horizontal, spacing: Padding.Two), stackItems: [StackItem(andContain: leftHeadline), StackItem(andContain: heart), rightLabelStackItem])
    }()
    public lazy var stack: Stack<StackModel> = {
        return Stack<StackModel>.createStack(with: [horizontalStack, leftBody, leftSubBody], axis: .vertical, spacing: 0)
    }()
    public var sizeObject: MFSizeObject? = MFSizeObject(standardSize: 12, standardiPadPortraitSize: 18)
    
    //-------------------------------------------------------
    // MARK: -  Lifecycle
    //-------------------------------------------------------
    open override func setupView() {
        super.setupView()

        rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
        rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
        addMolecule(stack)
        stack.restack()
        horizontalStack.restack()
    }
    
    public override func updateView(_ size: CGFloat) {
        super.updateView(size)
        if let dimension = sizeObject?.getValueBased(onSize: size) {
            heart.widthConstraint?.constant = dimension
        }
    }

    //------------------------------------------------------
    // MARK: - Molecule
    //------------------------------------------------------
    open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
        super.set(with: model, delegateObject, additionalData)
        
        guard let model = model as? ListStoreLocatorModel else { return }
        horizontalStack.updateContainedMolecules(with: [model.leftHeadline, model.heart, model.rightLabel], delegateObject, additionalData)
        leftBody.set(with: model.leftBody, delegateObject, additionalData)
        leftSubBody.set(with: model.leftSubBody, delegateObject, additionalData)
        updateAccessibilityLabel()
    }
    
    open override func alignAccessoryToHero() -> CGPoint? {
        let heroCenter = super.alignAccessoryToHero()
        
        if let heroCenter = heroCenter {
            let convertedPoint = horizontalStack.convert(heroCenter, from: self)
            rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - horizontalStack.bounds.midY
        }
        return heroCenter
    }
    
    public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
        if listItemModel?.action != nil {
            super.didSelectCell(at: index, delegateObject: delegateObject, additionalData: additionalData)
        } else {
            heart.tapAction()
            updateAccessibilityLabel()
        }
    }
    
    open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 120 }
    
    open override func reset() {
        super.reset()
        leftHeadline.setFontStyle(.BoldBodySmall)
        leftBody.setFontStyle(.RegularBodySmall)
        leftSubBody.setFontStyle(.RegularBodySmall)
        rightLabel.setFontStyle(.RegularBodySmall)
    }
    
    //--------------------------------------------------
    // MARK: - Accessibility
    //--------------------------------------------------
    
    func getAccessibilityMessage() -> String? {
        var message = ""
        heart.updateAccessibilityLabel()
        
        if let leftHeadlineText = leftHeadline.text, !leftHeadlineText.isEmpty {
            message += leftHeadlineText + ", "
        }
        
        if let leftBodyText = leftBody.text, !leftBodyText.isEmpty {
            message += leftBodyText + ", "
        }
        
        if let leftSubBodyText = leftSubBody.text, !leftSubBodyText.isEmpty {
            message += leftSubBodyText + ", "
        }
        
        if let rightLabelText = rightLabel.text, !rightLabelText.isEmpty {
            message += rightLabelText
        }
        return message.count > 0 ? message : nil
    }
    
    func updateAccessibilityLabel() {
        let hasHeart = !(horizontalStack.stackModel?.molecules[1].gone ?? true)
        if let accessoryView = accessoryView,
           hasHeart {
            // Both accessory and heart actions.
            isAccessibilityElement = false
            accessoryView.accessibilityLabel = getAccessibilityMessage()
            accessibilityElements = [accessoryView, heart]
        } else {
            // Make whole cell focusable if no action.
            isAccessibilityElement = true
            var message = getAccessibilityMessage()
            if hasHeart {
                accessibilityHint = heart.accessibilityHint
                if let heartLabel = heart.accessibilityLabel {
                    message = (message ?? "") + ", " + heartLabel
                }
            } else {
                accessibilityHint = nil
            }
            accessibilityLabel = message
        }
    }
    
    // Ensures voice over does not read "selected" after user triggers action on cell.
    override public var accessibilityTraits: UIAccessibilityTraits {
        get {
            if (accessoryView != nil) {
                return .button
            } else if (!(horizontalStack.stackModel?.molecules[1].gone ?? true)) {
                return heart.accessibilityTraits
            } else {
                return .none
            }
        }
        set { }
    }
}
