//
//  LiveTimerView.swift
//  LeCountdown
//
//  Created by Laurent Morvillier on 03/02/2023.
//

import SwiftUI

class LiveStopwatchModel: ObservableObject {
    
    @Published var endDate: Date? = nil
    
    func stop(_ stopwatch: Stopwatch) {
        
        let now = Date()
        self.endDate = now
        
        Conductor.maestro.stopStopwatch(stopwatch)
        
    }
}

struct SeparatorView: View {
    
    var body: some View {
        Spacer()
            .frame(minWidth: 0.0, maxWidth: .infinity, minHeight: 1.0, maxHeight: 1.0)
            .background(Color(white: 0.85))
            .padding(.vertical, 8.0)
    }

}

fileprivate let liveViewSize: CGFloat = 70.0
fileprivate let timerFontSize: CGFloat = 32.0

struct TimeView: View {
    
    var text: String
    
    var body: some View {
        Text(self.text)
            .font(.system(size: timerFontSize, weight: .medium))
            .minimumScaleFactor(0.1)
    }
    
}

struct LiveStopwatchView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    @EnvironmentObject var conductor: Conductor
    
    @StateObject var model: LiveStopwatchModel = LiveStopwatchModel()
    
    @State var stopwatch: Stopwatch
    var date: Date
    
    var body: some View {
        
        let running = (self.model.endDate == nil)
        
        VStack(alignment: .trailing) {
            
            if running {
                TimelineView(.periodic(from: self.date, by: 0.01)) { context in
                    
                    TimeView(text: self._formattedDuration(date: context.date))
                }
            } else {
                let duration = self.model.endDate?.timeIntervalSince(self.date) ?? 0.0
                TimeView(text: duration.hourMinuteSecondHS)
            }
            
//            if running {
//
////                Button {
////                    self.model.stop(stopwatch)
////                } label: {
////
////                    Image(systemName: "stop.circle.fill")
////                        .font(.title)
////                        .foregroundColor(.white)
////                        .cornerRadius(8.0)
////                        .frame(minWidth: 0.0, maxWidth: 60.0, minHeight: 0.0, maxHeight: .infinity)
////                }.background(.red)
//
//            } else {
//                GreenCheckmarkView()
//            }
//            SeparatorView()
            HStack {
                if !running {
                    GreenCheckmarkView()
                }
                Text(stopwatch.displayName.uppercased())
            }

        }.onTapGesture {
            withAnimation {
                if self.model.endDate == nil {
                    self.model.stop(stopwatch)
                } else {
                    self._dismiss()
                }
            }
        }
        .frame(height: liveViewSize)
//        .foregroundColor(.white)
        .monospaced()
//        .background(Color(white: 0.2))
//        .cornerRadius(16.0)
    }
    
    fileprivate func _dismiss() {
        conductor.removeLiveTimer(id: self.stopwatch.stringId)
    }
    
    fileprivate func _formattedDuration(date: Date) -> String {
        let duration = date.timeIntervalSince(self.date)
        return duration.hourMinuteSecondHS
    }
}

struct LiveCountdownView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    @EnvironmentObject var conductor: Conductor
    
    @State var countdown: Countdown
    var date: Date
    
    var body: some View {

        TimelineView(.periodic(from: self.date, by: 0.01)) { context in
            VStack(alignment: .trailing) {
                
                let running = self.date > context.date
                let cancelled = conductor.cancelledCountdowns.contains(where: { $0 == self.countdown.stringId })
                
                if cancelled {
                    TimeView(text: NSLocalizedString("Cancelled", comment: ""))
                } else if running {
                    TimeView(text: self._formattedDuration(date: context.date))
                } else {
                    TimeView(text: self.date.formatted(date: .omitted, time: .shortened))
                }
//                SeparatorView()
                HStack {
                    if cancelled {
                        XMarkView()
                    } else if !running {
                        GreenCheckmarkView()
                    }
                    Text(self.countdown.displayName.uppercased())
//                        .padding(.top, 2.0)
                }
                
            }
        }
        .contentShape(Rectangle()) // make the onTap react everywhere
        .onTapGesture {
            withAnimation {
                if conductor.currentCountdowns[self.countdown.stringId] != nil {
                    self._cancelCountdown()
                } else {
                    self._dismiss()
                }
            }
        }
        .frame(height: liveViewSize)
//        .foregroundColor(.white)
        .monospaced()
//        .background(Color(white: 0.2))
//        .cornerRadius(16.0)
    }
    
    fileprivate func _dismiss() {
//        conductor.cancelCountdown(id: self.countdown.stringId)
        conductor.removeLiveTimer(id: self.countdown.stringId)
    }
    
    fileprivate func _formattedDuration(date: Date) -> String {
        let duration = self.date.timeIntervalSince(date)
        return duration.minuteSecond
    }
    
    fileprivate func _cancelCountdown() {
        Conductor.maestro.cancelCountdown(id: self.countdown.stringId)
    }
    
}

struct LiveTimerListView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    @EnvironmentObject var conductor: Conductor
    
    var body: some View {
        
//        ScrollView {
            
            LazyVGrid(
                columns: self._columns(),
                alignment: .trailing,
                spacing: 0.0
            ) {
                
                ForEach(conductor.liveTimers) { liveTimer in
                    
                    if let timer: AbstractTimer = liveTimer.timer(context: self.viewContext) {
                        
                        switch timer {
                        case let cd as Countdown:
                            LiveCountdownView(countdown: cd, date: liveTimer.date)
                        case let sw as Stopwatch:
                            LiveStopwatchView(stopwatch: sw, date: liveTimer.date)
                        default:
                            Text("unmanaged timer: \(timer)")
                        }
                        
                    }
                    
                }
//            }
        }.padding()
        
    }
    
    fileprivate func _columnCount() -> Int {
        #if os(iOS)
        if UIDevice.isPhoneIdiom {
            return 2
        } else {
            return 3
        }
        #else
        return 3
        #endif
    }
    
    fileprivate func _columns() -> [GridItem] {
        return (0..<self._columnCount()).map { _ in GridItem(spacing: 20.0) }
    }
    
}

struct LiveTimerView_Previews: PreviewProvider {
    
    static var previews: some View {
//        LiveTimerListView().environmentObject(Conductor.maestro)
        
        Group {
            VStack(spacing: 20.0) {
                LiveCountdownView(countdown: Countdown.fake(context: PersistenceController.preview.container.viewContext), date: Date().addingTimeInterval(3600.0))
                    .environmentObject(Conductor.maestro)
                LiveStopwatchView(stopwatch: Stopwatch.fake(context: PersistenceController.preview.container.viewContext), date: Date())
                    .environmentObject(Conductor.maestro)
            }
        }.padding()
    }
    
}
