//
//  CardView.swift
//
//  Created by Muhammad Bassiouny on 5/3/23.
//

import UIKit
import MFSDK


class MFCardView: UIView {
    static let cardView = MFCardView()
    let cardPaymentView = MFPaymentCardView()
    
    @objc var paymentStyle: NSDictionary? {
        didSet {
            applyViewProps()
        }
    }
    
    private override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    internal required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupView()
    }
    
    private func setupView() {
        self.addSubview(cardPaymentView)
        cardPaymentView.translatesAutoresizingMaskIntoConstraints = false
        cardPaymentView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        cardPaymentView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        cardPaymentView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        cardPaymentView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        cardPaymentView.heightAnchor.constraint(equalToConstant: 220).isActive = true
        
        self.isUserInteractionEnabled = true
    }
    
    private func applyViewProps() {
        guard let props = paymentStyle else { return }
        let configure = MFCardConfigureBuilder.default
        
        if let data = try? JSONSerialization.data(withJSONObject: props, options: []),
           let cardViewStyle = try? JSONDecoder().decode(MFCardViewStyle.self, from: data) {
            
            if let cardHeight = cardViewStyle.cardHeight {
                configure.setCardHeight(cardHeight)
                self.cardPaymentView.MFSetHeight(cardHeight)
            }
            
            let nameLabel = cardViewStyle.label?.text?.holderName ?? ""
            let cardNumberLabel = cardViewStyle.label?.text?.cardNumber ?? ""
            let expiryDateLabel = cardViewStyle.label?.text?.expiryDate ?? ""
            let cvvLabel = cardViewStyle.label?.text?.securityCode ?? ""
            let showLabels = cardViewStyle.label?.display ?? true
            let fontWeight = toMFontWeight(cardViewStyle.label?.fontWeight)
            configure.setLabel(MFCardLabel(cardHolderNameLabel: nameLabel, cardNumberLabel: cardNumberLabel, expiryDateLabel: expiryDateLabel, cvvLabel: cvvLabel, showLabels: showLabels, fontWeight: fontWeight))
            
            let cardHolderNamePlaceholder = cardViewStyle.input?.placeHolder?.holderName ?? ""
            let cardNumberPlaceholder = cardViewStyle.input?.placeHolder?.cardNumber ?? ""
            let expiryDatePlaceholder = cardViewStyle.input?.placeHolder?.expiryDate ?? ""
            let cvvPlaceholder = cardViewStyle.input?.placeHolder?.securityCode ?? ""
            configure.setPlaceholder(MFCardPlaceholder(cardHolderNamePlaceholder: cardHolderNamePlaceholder, cardNumberPlaceholder: cardNumberPlaceholder, expiryDatePlaceholder: expiryDatePlaceholder, cvvPlaceholder: cvvPlaceholder))
            
            if let setHideCardIcon = cardViewStyle.hideCardIcons{
                configure.setHideCardIcon(setHideCardIcon)
            }
            
            var inputColor: UIColor = .black
            var labelColor: UIColor = .black
            var errorColor: UIColor = .red
            var borderColor: UIColor = .black
            var backgroundColor: UIColor = .white
            
            if let inputColorNumber = cardViewStyle.input?.color {
                inputColor = MFHelper.getColor(number: inputColorNumber)
            }
            if let labelColorNumber = cardViewStyle.label?.color {
                labelColor = MFHelper.getColor(number: labelColorNumber)
            }
            if let errorColorNumber = cardViewStyle.error?.borderColor {
                errorColor = MFHelper.getColor(number: errorColorNumber)
            }
            if let borderColorNumber = cardViewStyle.input?.borderColor {
                borderColor = MFHelper.getColor(number: borderColorNumber)
            }
            if let backgroundColorNumber = cardViewStyle.backgroundColor {
                backgroundColor = MFHelper.getColor(number: backgroundColorNumber)
            }

            configure.setBackgroundColor(backgroundColor)
            let theme = MFCardTheme(inputColor: inputColor, labelColor: labelColor, errorColor: errorColor, borderColor: borderColor)
            
            if let direction = cardViewStyle.direction,
               direction.lowercased() == "rtl" {
                theme.language = .arabic
            }
            
            configure.setTheme(theme)
            
            let inputHeight = cardViewStyle.input?.inputHeight ?? 32
            let inputMargin = cardViewStyle.input?.inputMargin ?? 0
            configure.setCardInput(MFCardInput(inputHeight: inputHeight, inputMargin: inputMargin))
            
            let hOffset = cardViewStyle.input?.boxShadow?.hOffset ?? 0
            let vOffset = cardViewStyle.input?.boxShadow?.vOffset ?? 0
            let blur = cardViewStyle.input?.boxShadow?.blur ?? 0
            let spread = cardViewStyle.input?.boxShadow?.spread ?? 0
            var boxShadowColor: UIColor = .gray
            if let boxShadowColorNumber = cardViewStyle.input?.boxShadow?.color {
                boxShadowColor = MFHelper.getColor(number: boxShadowColorNumber)
            }
            configure.setBoxShadow(MFBoxShadow(hOffset: hOffset, vOffset: vOffset, blur: blur, spread: spread, color: boxShadowColor))
            
            if let fontSize = cardViewStyle.input?.fontSize{
                configure.setFontSize(fontSize)
            }
            
            if let borderRadius = cardViewStyle.input?.borderRadius{
                configure.setBorderRadius(borderRadius)
            }
            
            if let fontFamily = cardViewStyle.input?.fontFamily {
                configure.setFontFamily(fontFamily)
            }

            if let inputBackgroundColorNumber = cardViewStyle.input?.backgroundColor {
                configure.setInputBackground(MFHelper.getColor(number: inputBackgroundColorNumber))
            }
        }
        
        cardPaymentView.configure = configure.build()
    }
    
    private func toMFontWeight(_ code: String?) -> MFFontWeight {
        switch code {
        case "Thin":
            return .thin
        case "ExtraLight":
            return .extraLight
        case "Light":
            return .light
        case "Normal":
            return .normal
        case "Medium":
            return .medium
        case "SemiBold":
            return .semiBold
        case "Bold":
            return .bold
        case "ExtraBold":
            return .extraBold
        case "Heavy":
            return .heavy
        default:
            return .medium
        }
    }
}

extension UIView {
    func MFSetHeight(_ newHeight: CGFloat, animateTime: TimeInterval? = nil) {
        if let heightConstrain = self.constraints.first(where: { $0.firstAttribute == .height && $0.relation == .equal }) {
            heightConstrain.constant = newHeight
            if let animateTime = animateTime {
                UIView.animate(withDuration: animateTime) {
                    self.superview?.layoutIfNeeded()
                }
            } else {
                self.superview?.layoutIfNeeded()
            }
        }
    }
}
