//
//  Styler.swift
//  MVMCoreUI
//
//  Created by Kevin Christiano on 4/1/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//

import Foundation


open class Styler {
    
    // MARK:- Font Enum
    public enum Font: String, Codable {
        case Title2XLarge
        case TitleXLarge
        case BoldTitleLarge
        case RegularTitleLarge
        case BoldTitleMedium
        case RegularTitleMedium
        case BoldBodyLarge
        case RegularBodyLarge
        case BoldBodySmall
        case RegularBodySmall
        case BoldMicro
        case RegularMicro
        
        // Legacy Fonts
        case H1
        case H32
        case H2
        case B20
        case H3
        case B1
        case B2
        case B3
        
        /// Returns the font size of the current enum case.
        public func pointSize() -> CGFloat {
            switch self {
            case .H1:
                return 40
                
            case .Title2XLarge:
                return 36
                
            case .TitleXLarge, .H32:
                return 32
                
            case .H2:
                return 25
                
            case .BoldTitleLarge,
                 .RegularTitleLarge:
                return 24
                
            case .BoldTitleMedium,
                 .RegularTitleMedium, .B20:
                return 20
                
            case .H3:
                return 18
                
            case .BoldBodyLarge,
                 .RegularBodyLarge:
                return 16
                
            case .BoldBodySmall, .B1,
                 .RegularBodySmall, .B2:
                return 13
                
            case .BoldMicro,
                 .RegularMicro, .B3:
                return 11
            }
        }
        
        public func color() -> UIColor {
            switch self {
            case .B3:
                return .mvmCoolGray6
                
            default:
                return .mvmBlack
            }
        }
        
        /// Determines if the selected font case is bold or regular.
        public func isBold() -> Bool {
            
            switch self {
            case .RegularTitleLarge,
                 .RegularTitleMedium, .B20,
                 .RegularBodyLarge,
                 .RegularBodySmall, .B2,
                 .RegularMicro, .B3:
                return false
                
            case .H1,
                 .Title2XLarge,
                 .TitleXLarge, .H32,
                 .H2,
                 .BoldTitleLarge,
                 .BoldTitleMedium,
                 .H3,
                 .BoldBodyLarge,
                 .BoldBodySmall, .B1,
                 .BoldMicro:
                return true
            }
        }
        
        /// Determines if the current enum is a legacy or modern font.
        public func isLegacyFont() -> Bool {
            
            switch self {
            case .Title2XLarge,
                 .TitleXLarge,
                 .RegularTitleLarge,
                 .RegularTitleMedium,
                 .RegularBodyLarge,
                 .RegularBodySmall,
                 .RegularMicro,
                 .BoldTitleLarge,
                 .BoldTitleMedium,
                 .BoldBodyLarge,
                 .BoldBodySmall,
                 .BoldMicro:
                return false
                
            case .H1,
                 .H32,
                 .H2,
                 .H3,
                 .B1,
                 .B2,
                 .B3,
                 .B20:
                return true
            }
        }
        
        /// Returns the font based on the declared enum case.
        public func getFont(_ genericScaling: Bool = true) -> UIFont {
            
            let size = genericScaling ? sizeFontGeneric(forCurrentDevice: pointSize()) : pointSize()
            
            if isLegacyFont() {
                switch self {
                case .B2, .B3, .B20:
                    return MFFonts.mfFont55Rg(size)
                    
                default:
                    return MFFonts.mfFont75Bd(size)
                }
            } else {
                if isBold() {
                    return size >= 15 ? MFFonts.mfFontDSBold(size) : MFFonts.mfFontTXBold(size)
                    
                } else {
                    return size >= 15 ? MFFonts.mfFontDSRegular(size) : MFFonts.mfFontTXRegular(size)
                }
            }
        }
        
        /// Styles the provided label to the declared enum Font case.
        public func styleLabel(_ label: UILabel, textColor: UIColor = .mvmBlack, genericScaling: Bool = true) {
            
            label.font = getFont(genericScaling)
            label.textColor = textColor
        }
    }
    
    public enum Button {
        
        public enum Style: String, Codable {
            case primary
            case secondary
        }
        
        public enum Size: String, Codable {
            case standard
            case tiny
            
            func getHeight() -> CGFloat {
                switch self {
                case .standard:
                    return 42
                    
                case .tiny:
                    return 20
                }
            }
        }
    }
    
    //--------------------------------------------------
    // MARK: - Functions
    //--------------------------------------------------
    
    open class func sizeObjectGeneric(forCurrentDevice size: CGFloat) -> MFSizeObject? {
        
        let sizeObject = MFSizeObject(standardSize: size, standardiPadPortraitSize: size * 1.3)
        sizeObject?.addLargerThanCustomSize(size * 1.4, forThreshold: MFSizeStandardiPadLandscapeThreshold)
        sizeObject?.addLargerThanCustomSize(size * 1.5, forThreshold: MFSizeiPadProLandscapeThreshold)
        
        return sizeObject
    }
    
    open class func sizeFontGeneric(forCurrentDevice size: CGFloat) -> CGFloat {
        sizeObjectGeneric(forCurrentDevice: size)?.getValueBasedOnApplicationWidth() ?? size
    }
    
    /// Provide additional size information to help calculate its intrinsic height.
    /// - Returns: The available spacing that can be used for intrinsic content width.
    open class func maxAvailableLayoutWidth(size: CGFloat) -> CGFloat {
        // The 2 is the product of both sides of padding.
        size - (Padding.Component.horizontalPaddingForSize(size) * 2)
    }
    
    //--------------------------------------------------
    // MARK: - Spacing
    //--------------------------------------------------
    
    open class func setDefaultMarginsFor(_ view: UIView?, size: CGFloat?, horizontal: Bool = true, vertical: Bool = false) {
        
        var horizontalPadding: CGFloat = Padding.Component.HorizontalMarginSpacing
        let verticalPadding: CGFloat = vertical ? Padding.Component.VerticalMarginSpacing : 0
        
        if let size = size {
            horizontalPadding = horizontal ? Padding.Component.horizontalPaddingForSize(size) : 0
        }
        
        DispatchQueue.main.async {
            MVMCoreUIUtility.setMarginsFor(view,
                                           leading: horizontalPadding,
                                           top: verticalPadding,
                                           trailing: horizontalPadding,
                                           bottom: verticalPadding)
        }
    }
    
    open class func setMarginsFor(_ view: UIView?, size: CGFloat, horizontal: CGFloat?, top: CGFloat, bottom: CGFloat) {
        
        let horizontalPadding: CGFloat = horizontal ?? Padding.Component.horizontalPaddingForSize(size)
        
        DispatchQueue.main.async {
            MVMCoreUIUtility.setMarginsFor(view,
                                           leading: horizontalPadding,
                                           top: top,
                                           trailing: horizontalPadding,
                                           bottom: bottom)
        }
    }
}
