//
//  AbbreviatedTimeAgoFormatStyle.swift
//  
//
//  Created by Shadowfacts on 4/9/23.
//

import Foundation

public struct AbbreviatedTimeAgoFormatStyle: FormatStyle {
    public typealias FormatInput = Date
    public typealias FormatOutput = String
    
    public func format(_ value: Date) -> String {
        let (amount, component) = timeAgo(value: value)
        
        switch component {
        case .year:
            return "\(amount)y"
        case .month:
            return "\(amount)mo"
        case .weekOfYear:
            return "\(amount)w"
        case .day:
            return "\(amount)d"
        case .hour:
            return "\(amount)h"
        case .minute:
            return "\(amount)m"
        case .second:
            if amount >= 3 {
                return "\(amount)s"
            } else {
                return "Now"
            }
        default:
            fatalError("Unexpected component: \(component)")
        }
    }
    
    private static let unitFlags = Set<Calendar.Component>([.second, .minute, .hour, .day, .weekOfYear, .month, .year])
    
    private func timeAgo(value: Date) -> (Int, Calendar.Component) {
        let calendar = NSCalendar.current
        let components = calendar.dateComponents(Self.unitFlags, from: value, to: Date())
        
        if components.year! >= 1 {
            return (components.year!, .year)
        } else if components.month! >= 1 {
            return (components.month!, .month)
        } else if components.weekOfYear! >= 1 {
            return (components.weekOfYear!, .weekOfYear)
        } else if components.day! >= 1 {
            return (components.day!, .day)
        } else if components.hour! >= 1 {
            return (components.hour!, .hour)
        } else if components.minute! >= 1 {
            return (components.minute!, .minute)
        } else {
            return (components.second!, .second)
        }
    }

}

public extension FormatStyle where Self == AbbreviatedTimeAgoFormatStyle {
    static var abbreviatedTimeAgo: Self {
        Self()
    }
}
