//
//  Lazy.swift
//  Tusker
//
//  Created by Shadowfacts on 12/4/22.
//  Copyright © 2022 Shadowfacts. All rights reserved.
//

import Foundation

/// A lazy initialization property wrapper that allows checking the initialization state.
@propertyWrapper
enum Lazy<Value> {
    case uninitialized(() -> Value)
    case initialized(Value)
    
    init(wrappedValue: @autoclosure @escaping () -> Value) {
        self = .uninitialized(wrappedValue)
    }
    
    /// Returns the contained value, initializing it if the value hasn't been accessed before.
    var wrappedValue: Value {
        mutating get {
            switch self {
            case .uninitialized(let closure):
                let value = closure()
                self = .initialized(value)
                return value
            case .initialized(let value):
                return value
            }
        }
    }
    
    /// Whether this Lazy has been initialized yet.
    var isInitialized: Bool {
        switch self {
        case .uninitialized(_):
            return false
        case .initialized(_):
            return true
        }
    }
    
    /// If this Lazy is initialized, this returns the value. Otherwise, it returns `nil`.
    var valueIfInitialized: Value? {
        switch self {
        case .uninitialized(_):
            return nil
        case .initialized(let value):
            return value
        }
    }
}
