//
//  Date.swift

import Foundation
import UIKit

public extension Date{
  
  static func getCurrentDateName() -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "EEEE"
    return dateFormatter.string(from: Date())
  }
  
  
  func localToUTC(date:String,originalFormat: String, convertFormat: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = originalFormat
    dateFormatter.calendar = NSCalendar.current
    dateFormatter.timeZone = TimeZone.current
    
    let dt = dateFormatter.date(from: date)
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    dateFormatter.dateFormat = convertFormat
    
    if dt != nil {
      
      return dateFormatter.string(from: dt!)
    }
    
    return ""
  }
  
  func UTCToLocal(date:String,originalFormat: String, convertFormat: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = originalFormat
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    
    let dt = dateFormatter.date(from: date)
    dateFormatter.timeZone = TimeZone.current
    dateFormatter.dateFormat = convertFormat
    if dt != nil {
      return dateFormatter.string(from: dt!)
    }
    
    return ""
    
  }
  
  static func convertStringToDate(formate:String,time:String) -> Date {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = formate
    let date = dateFormatter.date(from: time)
    if date != nil {
      return date!
    }
    return Date()
  }
  
  static func getDateLocal(from string: String) -> Date{
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = ServerDateTimeFormater
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    
    if let formatDate = dateFormatter.date(from: string){
      return formatDate
    }else{
      return Date()
    }
  }
  
    func getDateTime(from date: String,currentFormat:String = "",WithFormet : String,isUTCFormat:Bool = true) -> String{
    
    
    let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = currentFormat.isValidString() ? currentFormat : ServerDateTimeFormater//"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"//"hh:mm a"
        
        if isUTCFormat {
            
            dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
        }
    
    let dateNew = dateFormatter.date(from: date)
    
    let dateFormatterTime = DateFormatter()
    dateFormatterTime.dateFormat = WithFormet
    
    if dateNew != nil {
        return dateFormatterTime.string(from: dateNew!)
    }
    
    return ""

  }
  
  func getTime(from date: String) -> String{
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = DateTimeFormater//"hh:mm a"
    dateFormatter.timeZone = TimeZone(identifier: "Asia/Singapore")
    let dateNew = dateFormatter.date(from: date)
    
    let dateFormatterTime = DateFormatter()
    dateFormatterTime.dateFormat = "hh:mm a"
    
    if dateNew != nil {
        return dateFormatterTime.string(from: dateNew!)
    }
    
    return ""
  }
  
  static func getDate(_ firebaseTimeZone: Double) -> String{
    
    let date = Date(timeIntervalSince1970: firebaseTimeZone/1000)
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = ServerDateTimeFormater//"dd-MM-yyyy HH:mm:ss"
    let firebaseDate = dateFormatter.string(from: date)
    return firebaseDate
  }
  
  
  func getDayDifference(from date: Date) -> Int {
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = DateTimeFormater
    dateFormatter.timeZone = TimeZone.ReferenceType.local
    
    let localStrDate = dateFormatter.string(from: Date())
    dateFormatter.calendar = Calendar.current
    let localDate = dateFormatter.date(from: localStrDate)
    
    return Calendar.current.dateComponents([.day], from: date, to: localDate!).day ?? 0
  }
  
  
  func convertDateToString (convertFormat: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = convertFormat
    let dateObj = dateFormatter.string(from: self)
    return dateObj
  }
  
  func convertDateToString (date: Date, convertFormat: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = convertFormat
    //dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    let dateObj = dateFormatter.string(from: date)
    return dateObj
  }
  
  
  func convertDateToDisplayFormat(strDate:String,originalFormat: String, convertFormat: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = originalFormat
    let dateObj = dateFormatter.date(from: strDate)
    dateFormatter.dateFormat = convertFormat
    if dateObj != nil {
      
      let displayDate = dateFormatter.string(from: dateObj!)
      
      return displayDate
    }
    
    return "-"
  }
    
    func convertDateToDateFormat(strDate:String,originalFormat: String, convertFormat: String) -> Date {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = originalFormat
        let dateObj = dateFormatter.date(from: strDate)
        dateFormatter.dateFormat = convertFormat
        if dateObj != nil {
            
            return dateObj!
        }
        
        return Date()
    }
  
  
  func add(years: Int = 0, months: Int = 0, days: Int = 0, hours: Int = 0, minutes: Int = 0, seconds: Int = 0) -> Date {
    var targetDay: Date
    targetDay = Calendar.current.date(byAdding: .year, value: years, to: self)!
    targetDay = Calendar.current.date(byAdding: .month, value: months, to: targetDay)!
    targetDay = Calendar.current.date(byAdding: .day, value: days, to: targetDay)!
    targetDay = Calendar.current.date(byAdding: .hour, value: hours, to: targetDay)!
    targetDay = Calendar.current.date(byAdding: .minute, value: minutes, to: targetDay)!
    targetDay = Calendar.current.date(byAdding: .second, value: seconds, to: targetDay)!
    return targetDay
  }
  
  
  static func isOpenRest(strStartTime:String,endTime:String) -> Bool {
    
    let startDate = Date.convertStringToDate(formate: "hh:mma", time: strStartTime)
    let endDate = Date.convertStringToDate(formate: "hh:mma", time: endTime)
    
    
    let time1     = timeAsInteger(from: startDate)
    let time2     = timeAsInteger(from: endDate)
    
    let nowTime = timeAsInteger(from: Date())
    
    if time1 == time2 {
      return false
    }
    
    if time1 < time2 {
      if nowTime > time1 {
        if nowTime < time2 {
          return true
        }
      }
      return false
    }
    else {
      if nowTime > time1 || nowTime < time2 {
        return true
      }
      return false
    }
    
  }
  
  static func isOpenRestOrOpenLater(strStartTime:String,endTime:String) -> Bool {
    
    let startDate = Date.convertStringToDate(formate: "hh:mma", time: strStartTime)
    let endDate = Date.convertStringToDate(formate: "hh:mma", time: endTime)
    
    let time1     = timeAsInteger(from: startDate)
    let time2     = timeAsInteger(from: endDate)
    
    let nowTime = timeAsInteger(from: Date())
    
    if time1 == time2 {
      return false
    }
    
    if nowTime < time1 {
      return true
    }
    
    if time1 < time2 {
      if nowTime > time1 {
        if nowTime < time2 {
          return true
        }
      }
      return false
    }
    else {
      if nowTime > time1 || nowTime < time2 {
        return true
      }
      return false
    }
    
  }
  
  static func timeAsInteger(from date: Date) -> Int {
    let currentCal = Calendar.current
    let nowComps: DateComponents? = currentCal.dateComponents([.hour, .minute], from: date)
    return (nowComps?.hour)! * 100 + (nowComps?.minute)!
  }

    var millisecondsSince1970:Int64 {
        return Int64((self.timeIntervalSince1970 * 1000.0).rounded())
    }
    
    func years(from date: Date) -> Int {
        return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
    }
    /// Returns the amount of months from another date
    func months(from date: Date) -> Int {
        return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
    }
    /// Returns the amount of weeks from another date
    func weeks(from date: Date) -> Int {
        return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
    }
    /// Returns the amount of days from another date
    func days(from date: Date) -> Int {
        return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
    }
    /// Returns the amount of hours from another date
    func hours(from date: Date) -> Int {
        return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
    }
    /// Returns the amount of minutes from another date
    func minutes(from date: Date) -> Int {
        return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
    }
    /// Returns the amount of seconds from another date
    func seconds(from date: Date) -> Int {
        return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
    }
    /// Returns the amount of nanoseconds from another date
    func nanoseconds(from date: Date) -> Int {
        return Calendar.current.dateComponents([.nanosecond], from: date, to: self).nanosecond ?? 0
    }
    
    func offsetFrom(startDate : Date,endDate : Date) -> String {
        
        let dayHourMinuteSecond: Set<Calendar.Component> = [.day, .hour, .minute, .second]
        let difference = NSCalendar.current.dateComponents(dayHourMinuteSecond, from: startDate, to: endDate);
        
        //let seconds = "\(difference.second ?? 0)s"
        let minutes = "\(difference.minute ?? 0) min" + " "
        let hours = "\(difference.hour ?? 0) hours" + " " + minutes
        let days = "\(difference.day ?? 0) days" + " " + hours
        
        if let day = difference.day, day          > 0 { return days }
        if let hour = difference.hour, hour       > 0 { return hours }
        if let minute = difference.minute, minute > 0 { return minutes }
        //if let second = difference.second, second > 0 { return seconds }
        return ""
    }

    func timeAgoDisplay() -> String {
            var strTime = ""
            let secondsAgo = Int(Date().timeIntervalSince(self))
            let minute = 60
            let hour = 60 * minute
            let day = 24 * hour
            let week = 7 * day
            
            if secondsAgo < minute {
                if secondsAgo < 2 {
                      strTime = "just now"
                }else{
                    strTime = "\(secondsAgo)" + " seconds ago"
                }
            }
    //        else if secondsAgo < hour {
    //            strTime = "\(secondsAgo / minute) minutes ago"
    //        }
    //        else if secondsAgo < day {
    //            strTime = "\(secondsAgo / hour) hours ago"
    //        }
    //        else if secondsAgo < week {
    //            strTime = "\(secondsAgo / day) days ago"
    //        }else{
    //            strTime = "\(secondsAgo / week) weeks ago"
    //        }
            return strTime
        }
    func isEqual(_ date: Date) -> Bool {
        //return (self.compare(date) == .orderedSame)
        
        let order = Calendar.current.compare(self, to: date, toGranularity: .day)
        switch order {
        case .orderedSame:
            return true
        default:
            return false
        }
    }
    func minus(days d: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: -Int(d), weeks: 0, months: 0, years: 0)
    }
    fileprivate func addComponentsToDate(seconds sec: Int, minutes min: Int, hours hrs: Int, days d: Int, weeks wks: Int, months mts: Int, years yrs: Int) -> Date {
        var dc = DateComponents()
        dc.second = sec
        dc.minute = min
        dc.hour = hrs
        dc.day = d
        dc.weekOfYear = wks
        dc.month = mts
        dc.year = yrs
        return Calendar.current.date(byAdding: dc, to: self)!
    }
}
