//
//  WdtDailySummary.swift
//  1Weather
//
//  Created by Demid Merzlyakov on 26.02.2021.
//

import Foundation

struct WdtDailySummary: Codable {
    public var dateLocal: String
    public var weekDay: String
    
    public var minTempF: String?
    public var maxTempF: String?
    public var windSpeedKph: String?
    public var windDirection: String?
    public var weatherCode: String?
    public var precipitationProbability: String?
    public var sunriseUtc: String?
    public var sunsetUtc: String?
    public var sunState: CelestialState? // may be nil if micro update
    public var moonriseUtc: String?
    public var moonsetUtc: String?
    public var moonState: CelestialState? // may be nil if micro update
    public var moonPhase: MoonPhase? // may be nil if micro update
    
    private enum CodingKeys: String, CodingKey {
        case dateLocal = "summary_date"
        case weekDay = "day_of_week"
        
        case minTempF = "min_temp_F"
        case maxTempF = "max_temp_F"
        case windSpeedKph = "wnd_spd_kph"
        case windDirection = "wnd_dir"
        case weatherCode = "wx_code"
        case precipitationProbability = "pop"
        case sunriseUtc = "solunar_sunrise_utc"
        case sunsetUtc = "solunar_sunset_utc"
        case moonriseUtc = "solunar_moonrise_utc"
        case moonsetUtc = "solunar_moonset_utc"
    }
    
    private static let log = Logger(componentName: "WdtDailySummary")
    
    public func toAppModel(timeZone: TimeZone, updatedAt: Date) -> DailyWeather? {
        let log = WdtDailySummary.log
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MM/dd/yyyy"
        dateFormatter.timeZone = timeZone
        guard let date = dateFormatter.date(from: dateLocal) else {
            log.error("Failed to parse date from: \(dateLocal)")
            return nil
        }
        
        var weekDay = WeekDay(rawValue: self.weekDay)
        if weekDay == nil {
            var calendar = Calendar(identifier: .gregorian)
            calendar.timeZone = timeZone
            weekDay = WeekDay(grigorianWeekDayNumber: calendar.component(.weekday, from: date))
        }
        guard let weekDayUnwrapped = weekDay else {
            log.error("Couldn't parse week day: \(self.weekDay)")
            return nil
        }
        
        var result = DailyWeather(lastTimeUpdated: updatedAt, date: date, timeZone: timeZone, weekDay: weekDayUnwrapped)
        if let weatherCode = self.weatherCode {
            result.type = WdtWeatherCode(rawValue: weatherCode)?.toAppModel() ?? .unknown
        }
        
        result.minTemp = Temperature(valueString: minTempF, unit: .fahrenheit)
        result.maxTemp = Temperature(valueString: maxTempF, unit: .fahrenheit)
        result.windSpeed = WindSpeed(valueString: self.windSpeedKph, unit: .kilometersPerHour)
        result.windDirection = WindDirection(rawValue: windDirection ?? "")
        
        if let precipitationProbability = Percent(self.precipitationProbability ?? ""), precipitationProbability >= 0, precipitationProbability <= 100 {
            result.precipitationProbability = precipitationProbability
        }
        
        let sunMoonDateFormatter = DateFormatter()
        sunMoonDateFormatter.timeZone = TimeZone(identifier: "UTC")
        sunMoonDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        if let sunriseUtc = sunriseUtc {
            result.sunrise = sunMoonDateFormatter.date(from: sunriseUtc)
        }
        if let sunsetUtc = sunsetUtc {
            result.sunset = sunMoonDateFormatter.date(from: sunsetUtc)
        }
        result.sunState = sunState
        if let moonriseUtc = moonriseUtc {
            result.moonrise = sunMoonDateFormatter.date(from: moonriseUtc)
        }
        if let moonsetUtc = moonsetUtc {
            result.moonset = sunMoonDateFormatter.date(from: moonsetUtc)
        }
        result.moonState = moonState
        result.moonPhase = moonPhase
        return result
    }
}
