//
//  StatsView.swift
//  LeCountdown
//
//  Created by Laurent Morvillier on 17/02/2023.
//

import SwiftUI
import CoreData

enum Stat: Int, CaseIterable {
    case count
    case totalDuration
    case averageDuration
    
    var localizedName: String {
        switch self {
        case .count: return NSLocalizedString("Count", comment: "")
        case .totalDuration: return NSLocalizedString("Duration", comment: "")
        case .averageDuration: return NSLocalizedString("Average duration", comment: "")
        }
    }
    
    var field: String {
        switch self {
        case .count:
            return "duration"
        case .totalDuration:
            return "duration"
        case .averageDuration:
            return "duration"
        }
    }
    
    var function: String {
        switch self {
        case .count:
            return "count:"
        case .totalDuration:
            return "sum:"
        case .averageDuration:
            return "average:"
        }
    }
    
    var stringIdentifier: String {
        return self.function + self.field
    }
    
    var type: NSAttributeType {
        switch self {
        case .count:
            return .integer32AttributeType
        default:
            return .doubleAttributeType
        }
    }
}

struct StatValue: Identifiable {
    
    var id: Int { return self.stat.rawValue }
    
    var stat: Stat
    var value: NSDecimalNumber
    
    var formattedValue: String {
        
        switch self.stat {
        case .averageDuration, .totalDuration:
            return self.value.doubleValue.minuteSecond
        default:
            let formatter: NumberFormatter = NumberFormatter()
            return formatter.string(from: self.value) ?? "--"
        }
        
    }
}

class StatModel: ObservableObject {
    
    @Published var statValues: [StatValue] = []
    
    @Published var isComputing = false
    
    @Published var error: Error? = nil
    
    func compute(activity: Activity) {
        
        self.isComputing = true
        
        PersistenceController.shared.container.performBackgroundTask { context in
            
            var values: [StatValue] = []
            
            do {
                values = try context.compute(activity: activity, stats: Stat.allCases)
            } catch {
                Logger.error(error)
                self.error = error
            }
            
            DispatchQueue.main.async {
                self.statValues = values
                self.isComputing = false
            }
            
        }
        
    }
    
}

struct StatsView: View {
    
    var activity: Activity
    
    @StateObject var model: StatModel = StatModel()
    
    var body: some View {
        
        VStack() {
            
            if self.model.isComputing {
                ProgressView()
                    .progressViewStyle(CircularProgressViewStyle())
            } else {
                HStack {
                    ForEach(self.model.statValues) { statValue in
                        StatView(name: statValue.stat.localizedName, value: statValue.formattedValue)
                    }
                }
            }
            Spacer()
        }
        .onAppear() {
            self.model.compute(activity: self.activity)
        }
        .navigationTitle(self.activity.name ?? "")
    }
    
}

struct StatView: View {
    
    var name: String
    var value: String
    
    var body: some View {
        VStack(alignment: .leading) {
            Text(self.name.uppercased()).font(.caption)
            Text(self.value).font(.title)
        }
    }
    
}

struct StatsView_Previews: PreviewProvider {
    static var previews: some View {
        StatsView(activity: Activity.fake(context: PersistenceController.preview.container.viewContext))
    }
}
