//
//  Date+Extensions.swift
//  Reflect (iOS)
//
//  Created by Trey Tartt on 2/19/22.
//

import Foundation

extension Date: @retroactive RawRepresentable {
    public var rawValue: String {
        self.timeIntervalSinceReferenceDate.description
    }
    
    public init?(rawValue: String) {
        self = Date(timeIntervalSinceReferenceDate: Double(rawValue) ?? 0.0)
    }
    
    var startOfDay: Date {
        return Calendar.current.startOfDay(for: self)
    }
    
    var startOfMonth: Date {
        
        let calendar = Calendar(identifier: .gregorian)
        let components = calendar.dateComponents([.year, .month], from: self)
        
        return  calendar.date(from: components)!
    }
    
    var endOfDay: Date {
        var components = DateComponents()
        components.day = 1
        components.second = -1
        return Calendar.current.date(byAdding: components, to: startOfDay)!
    }
    
    var endOfMonth: Date {
        var components = DateComponents()
        components.month = 1
        components.second = -1
        return Calendar(identifier: .gregorian).date(byAdding: components, to: startOfMonth)!
    }
    
    func toLocalTime() -> Date {
        let timezone    = TimeZone.current
        let seconds     = TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }
    
    var weekday: Int {
        Calendar.current.component(.weekday, from: self)
    }
    
    var firstDayOfTheMonth: Date {
        Calendar.current.dateComponents([.calendar, .year,.month], from: self).date!
    }
    
    static public func dates(from fromDate: Date, toDate: Date, includingToDate: Bool = false) -> [Date] {
        var dates: [Date] = []
        var date = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: fromDate)!
        let toDate = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: toDate)!
        
        if includingToDate {
            while date <= toDate {
                dates.append(date)
                guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: date) else { break }
                date = newDate
            }
        } else {
            while date < toDate {
                dates.append(date)
                guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: date) else { break }
                date = newDate
            }
        }
        
        return dates
    }
    
    static func dateRange(monthInt: Int, yearInt: Int) -> (startDate: Date, endDate: Date) {
        var dateComponents = DateComponents()
        dateComponents.year = yearInt
        dateComponents.month = monthInt
        dateComponents.day = 3
        dateComponents.hour = 12
        var userCalendar = Calendar(identifier: .gregorian)
        userCalendar.timeZone = TimeZone(secondsFromGMT: 0)!
        let someDateTime = userCalendar.date(from: dateComponents)!
        
        let startDate = someDateTime.startOfMonth
        var endDate = someDateTime.endOfMonth
        endDate = Calendar.current.date(byAdding: .hour, value: -8, to: endDate)!
        
        return (startDate, endDate)
    }
    
    func formattedDate() -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM dd, yyyy"
        return dateFormatter.string(from: self)
    }
}
