Noobish1/WeatherRules

View on GitHub
App/WhatToWear/WhatToWear/Views/ValueButtonContainerView.swift

Summary

Maintainability
A
0 mins
Test Coverage
import UIKit
import WhatToWearCoreUI

internal final class ValueButtonContainerView: CodeBackedView, Accessible {
    // MARK: AccessibilityIdentifiers
    internal enum AccessibilityIdentifiers: String, AccessibilityIdentifiersProtocol {
        internal typealias EnclosingType = ValueButtonContainerView

        case numberLabel = "numberLabel"
        case tickLabel = "tickLabel"
        case doubleButton = "doubleButton"
        case basicButton = "basicButton"
        case timeRangeView = "timeRangeView"
    }

    internal enum State: Equatable {
        case notVisible
        case doubleButton(DoubleInputButton)
        case basicButton(BasicValueButton)
        case timeRangeView(TimeRangeView)

        // MARK: computed properties
        fileprivate var tickColor: UIColor {
            switch self {
                case .notVisible:
                    return .clear
                case .doubleButton(let button):
                    switch button.buttonState {
                        case .noSelection, .highlightedNoSelection: return .clear
                        case .selection: return .white
                    }
                case .basicButton(let button):
                    switch button.state {
                        case .noSelection, .highlightedNoSelection: return .clear
                        case .selection: return .white
                    }
                case .timeRangeView:
                    // We always have a timeRange
                    return .white
            }
        }

        fileprivate var backgroundColor: UIColor {
            switch self {
                case .notVisible:
                    return .clear
                case .doubleButton(let button):
                    return button.buttonState.backgroundColor
                case .basicButton(let button):
                    return button.state.backgroundColor
                case .timeRangeView:
                    // We always have a timeRange
                    return Colors.completed
            }
        }

        fileprivate var view: UIView? {
            switch self {
                case .notVisible: return nil
                case .doubleButton(let doubleButton): return doubleButton
                case .basicButton(let basicButton): return basicButton
                case .timeRangeView(let view): return view
            }
        }
    }

    // MARK: properties
    private let numberLabel = UILabel().then {
        $0.textColor = .white
        $0.text = NSLocalizedString("3", comment: "")
        $0.font = .boldSystemFont(ofSize: 40)
        $0.wtw_setAccessibilityIdentifier(AccessibilityIdentifiers.numberLabel)
    }
    private lazy var tickLabel = UILabel().then {
        $0.textColor = state.tickColor
        $0.text = NSLocalizedString("✓", comment: "")
        $0.font = .systemFont(ofSize: 40)
        $0.wtw_setAccessibilityIdentifier(AccessibilityIdentifiers.tickLabel)
    }
    private let layout: AddConditionViewController.Layout
    internal private(set) var state: State = .notVisible

    // MARK: init/deinit
    internal init(layout: AddConditionViewController.Layout) {
        self.layout = layout

        super.init(frame: .zero)

        backgroundColor = state.backgroundColor
        layer.borderWidth = 1
        layer.borderColor = UIColor.white.cgColor

        transition(to: state, force: true)
    }

    // MARK: layout
    private func layoutBasic(view: UIView) {
        add(subview: view, withConstraints: { make in
            make.edges.equalToSuperview()
            make.height.equalTo(80).priority(.high)
            make.height.greaterThanOrEqualTo(50)
        })

        layoutNumberAndTickLabels()
    }

    private func layout(timeRangeView: TimeRangeView) {
        timeRangeView.wtw_setAccessibilityIdentifier(AccessibilityIdentifiers.timeRangeView)

        add(subview: timeRangeView, withConstraints: { make in
            make.top.equalToSuperview()
            make.leading.equalToSuperview().offset(40)
            make.trailing.equalToSuperview().inset(40)
            make.bottom.equalToSuperview()
            make.height.equalTo(80).priority(.high)
            make.height.greaterThanOrEqualTo(50)
        })

        layoutNumberAndTickLabels()
    }

    private func layoutNumberAndTickLabels() {
        add(subview: numberLabel, withConstraints: { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(layout.outerXPadding)
        })
        add(subview: tickLabel, withConstraints: { make in
            make.trailing.equalToSuperview().inset(layout.outerXPadding)
            make.centerY.equalToSuperview()
        })
    }

    private func layout(for state: State) {
        switch state {
            case .timeRangeView(let view):
                layout(timeRangeView: view)
            case .notVisible:
                break
            case .basicButton(let view):
                view.wtw_setAccessibilityIdentifier(AccessibilityIdentifiers.basicButton)
                layoutBasic(view: view)
            case .doubleButton(let view):
                view.wtw_setAccessibilityIdentifier(AccessibilityIdentifiers.doubleButton)
                layoutBasic(view: view)
        }
    }

    // MARK: transition
    internal func transition(to newState: State, force: Bool = false) {
        guard force || state != newState else { return }

        subviews.forEach { $0.removeFromSuperview() }

        layout(for: newState)

        tickLabel.textColor = newState.tickColor
        backgroundColor = newState.backgroundColor

        self.state = newState
    }
}