// // TitleLockupStandardStyleConfiguration.swift // VDS // // Created by Matt Bruce on 6/29/23. // import Foundation import UIKit import VDSTokens extension TitleLockup { /// Configuration that will set the spacing between labels based off their textStyles. public struct StandardStyleConfigurationProvider { /// Array of standard style configurations. public var styleConfigurations: [StandardStyleConfiguration] public init(styleConfigurations: [StandardStyleConfiguration]) { self.styleConfigurations = styleConfigurations } /// Will find a standard style configuration for the title standard style against the running device type. /// - titleStandardStyle: title standard style /// - Returns: Standard Style configuration that matches public func configuration(for titleStandardStyle: TitleStandardStyle) -> StandardStyleConfiguration? { let deviceType: StandardStyleConfiguration.DeviceType = UIDevice.isIPad ? .iPad : .iPhone guard let config: StandardStyleConfiguration = styleConfigurations.first(where: { return titleStandardStyle.isWithin($0.titleStandardStyles) && ($0.deviceType == deviceType || $0.deviceType == .all )}) else { return nil } return config } /// Determines if there is a configuration for this title style as well as a matching spacing configuration against the other standard style. /// - Parameters: /// - otherStandardStyle: other standard style /// - titleStandardStyle: title standard style /// - Returns: Whether or not there is a public func isValid(otherStandardStyle: OtherStandardStyle, for titleStandardStyle: TitleStandardStyle) -> Bool { guard let config = configuration(for: titleStandardStyle) else { return false } return otherStandardStyle.isWithin(config.spacingConfigurations.flatMap {$0.otherStandardStyles}) } /// Will find the spacing for a specific title standard style against a other standard style. If one isn't found a default spacing is returned. /// - Parameters: /// - titleStandardStyle: title standard style /// - otherStandardStyle: other standard style /// - Returns: Tuple of the standard style as well as the top and bottom spacing. public func spacing(for titleStandardStyle: TitleStandardStyle, otherStandardStyle: OtherStandardStyle) -> (otherStandardStyle: OtherStandardStyle, topSpacing: CGFloat, bottomSpacing: CGFloat)? { guard let config = configuration(for: titleStandardStyle) else { return nil } return config.styleSpacing(for: otherStandardStyle) } } /// Configuration that will set the spacing between labels based off the device type and their textStyles. public struct StandardStyleConfiguration { /// Enum for the devices for this configuration. public enum DeviceType { case iPhone, iPad, all } /// Device type for this configuration. public var deviceType: DeviceType /// Array of title standard styles, first style is always the default. public var titleStandardStyles:[TitleStandardStyle] /// Array of spacing configurations for spacing. public var spacingConfigurations: [SpacingConfiguration] public init(deviceType: DeviceType, titleStandardStyles: [TitleStandardStyle], spacingConfigurations: [SpacingConfiguration]) { self.deviceType = deviceType self.titleStandardStyles = titleStandardStyles self.spacingConfigurations = spacingConfigurations } /// Flattend array of all spacingConfigurations array of other standard styles. public var allOtherStandardStyles: [OtherStandardStyle] { spacingConfigurations.flatMap {$0.otherStandardStyles} } /// Takes a other standard style and will either find the spacing configuration that matches or returns a default top and bottom spacing. /// - Parameter otherStandardStyle: other standard style you need to find the configuration for top and bottom spacing /// - Returns: Tuple of the other standard style passed in and the configuration for top and bottom spacing. public func styleSpacing(for otherStandardStyle: OtherStandardStyle) -> (otherStandardStyle: OtherStandardStyle, topSpacing: CGFloat, bottomSpacing: CGFloat) { //set default return other style what you pass in var realOtherStyle = otherStandardStyle //flatten all of the other styles registered for the title styles let allOtherStyles = spacingConfigurations.flatMap {$0.otherStandardStyles} //get the default other style incase what is passed isn't within the registered collection if let first = allOtherStyles.first, !realOtherStyle.isWithin(allOtherStyles) { realOtherStyle = first } //get the config against the other style or return defaults guard let styleSpacing = spacingConfigurations.first(where: {realOtherStyle.isWithin($0.otherStandardStyles)}) else { return (realOtherStyle, VDSLayout.space2X, VDSLayout.space2X) } return (realOtherStyle, styleSpacing.topSpacing, styleSpacing.bottomSpacing) } } /// Configuration to define spacing for an array of standard styles. public struct SpacingConfiguration { /// Array of other standard styles public var otherStandardStyles: [OtherStandardStyle] /// Configuration of topSpacing for the other standard styles public var topSpacing: CGFloat /// Configuration of bottomSpacing for the other standard styles public var bottomSpacing: CGFloat public init(otherStandardStyles: [OtherStandardStyle], topSpacing: CGFloat, bottomSpacing: CGFloat) { self.otherStandardStyles = otherStandardStyles self.topSpacing = topSpacing self.bottomSpacing = bottomSpacing } } }