//
//  DateFormatterLib.swift
//  WOKA
//
//  Created by MacBook Pro on 08/05/24.
//

import UIKit

class DateFormatterLib{
    
    static func getMinutesDifferenceFromTwoDates(start: Date, end: Date) -> Int{
        
        let diff = Int(end.timeIntervalSince1970 - start.timeIntervalSince1970)
        let hours = diff / 3600
        let minutes = (diff - hours * 3600) / 60
        return minutes
    }
    
    static func convertToDate(dateFormat : DateFormats , dateStr : String) -> Date {
        
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
        dateFormatter.dateFormat = dateFormat.rawValue
        let date = dateFormatter.date(from:dateStr)!
        return date
    }
    
    static func dateConvert (date : String) -> String?{  // d-MMMM-yyyy h:mm a -> 27-June-2022 1:10 PM
        let isoDate = date
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        let date = dateFormatter.date(from:isoDate)!
        dateFormatter.dateFormat = "d-MMMM-yyyy h:mm a"
        let resultString = dateFormatter.string(from: date)
        return resultString
    }
    
    static func getDate(date : String) -> String?{  // d-MMMM-yyyy h:mm a -> 27-June-2022 1:10 PM
        let isoDate = date
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        let date = dateFormatter.date(from:isoDate)!
        dateFormatter.dateFormat = "d-MMMM-yyyy"
        let resultString = dateFormatter.string(from: date)
        return resultString
    }
    
    static func getTime(date : String) -> String?{  // d-MMMM-yyyy h:mm a -> 27-June-2022 1:10 PM
        let isoDate = date
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        let date = dateFormatter.date(from:isoDate)!
        dateFormatter.dateFormat = "h:mm a"
        let resultString = dateFormatter.string(from: date)
        return resultString
    }
    
    static func time(date : Date)-> String{
        let formatter = DateFormatter()
        formatter.dateFormat = "h:mm a"
        let currentTime = formatter.string(from: date)
        return currentTime
    }
    
    static func date(date : Date)-> String{
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        let currentTime = formatter.string(from: date)
        return currentTime
    }
    
    static func timeFormat(dateStr : String) -> String?{  // am pm to 24 hour
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "hh:mm a"
        let item = dateStr
        let date = dateFormatter.date(from: item)!
        dateFormatter.dateFormat = "HH:mm"
        let currentTime = dateFormatter.string(from: date)
        return currentTime
    }
    
    static func addMinToString(data : String , minToAdd : Double , format : DateFormats) -> (String? , Date?){
        let isoDate = data
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        let dateMod = dateFormatter.date(from:isoDate)!
        let minAdded = dateMod.addingTimeInterval(minToAdd * 60)
        dateFormatter.dateFormat = format.rawValue
        let resultString = dateFormatter.string(from: minAdded)
        return (resultString,minAdded)
    }
    
    static func addSecondToString(data : String , secondToAdd : Double , format : DateFormats) -> (String? , Date?){
        let isoDate = data
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        let dateMod = dateFormatter.date(from:isoDate)!
        let minAdded = dateMod.addingTimeInterval(secondToAdd)
        dateFormatter.dateFormat = format.rawValue
        let resultString = dateFormatter.string(from: minAdded)
        return (resultString,minAdded)
    }
    
    static func dateMods(dateStr : String,dateCurrentFormat : DateFormats, dateReturnFormat : DateFormats,stringOrDate : StringOrDate) -> (String?,Date?){
        if dateStr == ""{
            return ("",nil)
        }
        let isoDate = dateStr
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX  1991-11-29 00:00:00
        dateFormatter.dateFormat = dateCurrentFormat.rawValue
        let date = dateFormatter.date(from:isoDate)!
        dateFormatter.dateFormat = dateReturnFormat.rawValue
        
        switch stringOrDate {
        case .date:
            return (nil,date)
        case .string:
            let resultString = dateFormatter.string(from: date)
            return (resultString,nil)
        case .both:
            let resultString = dateFormatter.string(from: date)
            return (resultString,date)
        }
    }
    
    static func abbrevationTimeConversion(dateStr : String, dateCurrentFormat : DateFormats, dateReturnFormat : DateFormats, timeZoneAbbrevation : TimeZoneAbbreviation) -> String?{
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = dateCurrentFormat.rawValue
        dateFormatter.timeZone = TimeZone(abbreviation: timeZoneAbbrevation.rawValue)
        
        if let date = dateFormatter.date(from: dateStr) {
            dateFormatter.timeZone = TimeZone.current
            dateFormatter.dateFormat = dateReturnFormat.rawValue
            
            return dateFormatter.string(from: date)
        }
        return nil
    }
    
    static func dateModsDate(date : Date, dateReturnFormat : DateFormats,stringOrDate : StringOrDate) -> (String?,Date?){
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = dateReturnFormat.rawValue
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX  1991-11-29 00:00:00

        let dateFormatted = dateFormatter.string(from: date)
        switch stringOrDate {
        case .date:
            return (nil,date)
        case .string:
//            let resultString = dateFormatter.string(from: date)
            return (dateFormatted,nil)
        case .both:
            return (dateFormatted,date)
        }
    }
    
    static func convertTimeStringToCurrentDate(time : String, format : DateFormats) -> Date?{
        // Step 1: Get the current date
        let currentDate = Date()
        
        // Step 2: Parse the time string
        let timeString = time // Replace with your desired time string
        let timeFormatter = DateFormatter()
        timeFormatter.timeZone = TimeZone.current // Use the current time zone
        timeFormatter.locale = Locale(identifier: "en_US_POSIX") // set locale to reliable US_POSIX  1991-11-29 00:00:00

        timeFormatter.dateFormat = format.rawValue
        if let time = timeFormatter.date(from: timeString) {
            // Step 3: Combine the date and time
            let calendar = Calendar.current
            let combinedDate = calendar.date(bySettingHour: calendar.component(.hour, from: time),
                                             minute: calendar.component(.minute, from: time),
                                             second: calendar.component(.second, from: time),
                                             of: currentDate)
            
            if let combinedDate = combinedDate {
                // Now, combinedDate contains the current date with the time from the time string
                return combinedDate
            } else {
                return nil
            }
        } else {
            return nil
        }
        
    }
    
    static func dateDifferenceINT(date1 : Date, date2 : Date) -> Int{
        // Calculate the difference in seconds
        let timeInterval = date2.timeIntervalSince(date1)

        // Convert the time interval to an integer representing the difference in seconds
        let differenceInSeconds = Int(timeInterval)

        // If you want the difference in minutes, divide by 60
//        let differenceInMinutes = Int(timeInterval / 60)

        // If you want the difference in hours, divide by 3600
//        let differenceInHours = Int(timeInterval / 3600)
        
        return differenceInSeconds
    }
}

extension Date {
    func withAddedMinutes(minutes: Double) -> Date {
         addingTimeInterval(minutes * 60)
    }

    func withAddedHours(hours: Double) -> Date {
         withAddedMinutes(minutes: hours * 60)
    }
    
    static func -(lhs: Date, rhs: Int) -> Date {
        return Calendar.current.date(byAdding: .day, value: -rhs, to: lhs)!
    }
}

//enum DateFormats: String, CaseIterable {
//    case yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"
//    case yyyy_MM_dd_T_HH_mm_ss_SSSZ = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
//    case HH_mm = "HH:mm"
//    case yyyy_MM_dd = "yyyy-MM-dd"
//    case HH_mm_ss = "HH:mm:ss"
//    case yyyy_MM_dd_HH_mm_ss_Z = "yyyy-MM-dd HH:mm:ss Z"  //2023-02-28 03:00:29 +0000
//    case dd_MM_yyyy = "dd-MM-yyyy"  // 26-06-1991
//}

enum StringOrDate {
    case date
    case string
    case both
}

enum DateFormats: String, CaseIterable {
    case d = "d" // 2
    case EEEE = "EEEE" // wednesday
    case EEE = "EEE" // wed
    case yyyy = "yyyy" // year 2023
    case yyyy_MM_dd_T_HH_mm_ss_SSSZ = "yyyy_MM_dd_T_HH_mm_ss_SSSZ"
    
    case yyyy_MM_dd_THH_mm_ss_SSSZ = "yyyy_MM_dd_THH:mm:ss.SSSZ" // 2024-05-21T17:50:15.000000Z

    case yyyy_MM_ddTHH_mm_ss_ssZ = "yyyy-MM-dd'T'HH:mm:ss:ssZ" //

    case yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss" // 2023-07-25 14:03:07
    
    case yyyy_MM_dd = "yyyy-MM-dd"
    case MMMM_d_yyyy_h_mm_a = "MMMM d, yyyy, h:mm a" // December 6, 2022, 3:55 PM
    
    
    case d_MMM_yyyy_at_h_mm_a = "d MMM yyyy 'at' h:mm a" // 27 Jan 2023 at 4:30 pm

    case d_MMMM_yyyy_h_mm_a = "d MMMM yyyy, h:mm a" //2 Dec 2022, 12:34 PM

    case dd_MM_yyyy = "dd-MM-yyyy"  // 26-06-1991
    
    case MM_dd_yyyy = "MM-dd-yyyy"  // 06-26-1991
    
    case h_mm_a_d_MMM_yyyy = "h:mm a, d MMM yyyy"  // 2:45 pm, 22 Sep 2022
    
    case h_mm_a_MMM_d_yyyy = "h:mm a, MMM d yyyy" // 11:07 AM, Aug 16 2022
    
    case d_MMM_yyyy = "d MMM yyyy" // 28 Nov 2022
    case d_MMMM_yyyy = "d MMMM yyyy" // 28 November 2022
    case d_MMM__yyyy = "d MMM, yyyy" // 28 Nov, 2022
    case MMM_d_yyyy = "MMM d, yyyy" // Nov 28, 2022
    case MMMM_d = "MMMM, d" // March 16
    
    case d__MM = "d/MM"
    
    // Times
    case HH_mm = "HH:mm"
    case HH_mm_ss = "HH:mm:ss"
    case h_mm_a = "h:mm a"
    case h_a = "hh a"
    case h_mm_ss_a = "h:mm:ss a"
    case d_MM = "d MMM" // 12 Oct
    case h__mm__a = "h : mm a"
}

// List of abbrevation for different zones
enum TimeZoneAbbreviation: String {
    case UTC = "UTC"
    case GMT = "GMT"
    case EST = "EST"
    case CST = "CST"
    case MST = "MST"
    case PST = "PST"
    case AST = "AST"
    case AKST = "AKST"
    case HST = "HST"
    case AEDT = "AEDT"
    case AEST = "AEST"
    case ACDT = "ACDT"
    case ACST = "ACST"
    case AWST = "AWST"
    case JST = "JST"
    case KST = "KST"
    case IST = "IST"
    case CET = "CET"
    case CEST = "CEST"
    case EET = "EET"
    case MSK = "MSK"
    case NZST = "NZST"
    case NST = "NST"
    
    // Example usage:
//    let timeZone: TimeZoneAbbreviation = .EST
//    print("Time Zone Abbreviation: \(timeZone.rawValue)")
}
