//
//  DialView.swift
//  LeCountdown
//
//  Created by Laurent Morvillier on 02/02/2023.
//

import SwiftUI

struct DialView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @EnvironmentObject var boringContext: BoringContext
    @EnvironmentObject var conductor: Conductor

    @State var timer: AbstractTimer
    var isEditingBinding: Binding<Bool>
    
    var frameSize: CGFloat
    
    var handler: ((AbstractTimer) -> ())? = nil
    
    var body: some View {
        ZStack {
            
            switch self.isEditingBinding.wrappedValue {
            case false:
                Button {
                    self._launchTimer()
                } label: {
                    VStack {
                        Spacer()
                        self._dialView().padding(.horizontal)
                        Spacer()
                    }
                }
            case true:
                NavigationLink {
                    self._editView(timer: timer, isPresented: $boringContext.isShowingNewData)
                } label: {
                    VStack {
                        Spacer()
                        self._dialView().padding(.horizontal)
                        Spacer()
                    }
                }
            }
            
        }.background(Color(white: self.isEditingBinding.wrappedValue ? 0.1 : 0.95))
        .frame(width: frameSize, height: 80.0)
        .cornerRadius(20.0)
    }
    
    @ViewBuilder
    fileprivate func _dialView() -> some View {
        Group {
            switch self.timer {
            case let countdown as Countdown:
                CountdownDialView(countdown: countdown, isEditing: self.isEditingBinding.wrappedValue)
                    .environmentObject(Conductor.maestro)
            case let alarm as Alarm:
                AlarmDialView(alarm: alarm)
                    .environmentObject(Conductor.maestro)
            case let stopwatch as Stopwatch:
                StopwatchDialView(stopwatch: stopwatch)
                    .environmentObject(Conductor.maestro)
            default:
                Text("missing dial view")
            }
        }
        .monospaced()
        .font(.system(size: 16.0))
        .foregroundColor(Color.white)
    }
    
    @ViewBuilder
    fileprivate func _editView(timer: AbstractTimer, isPresented: Binding<Bool>) -> some View {
        switch timer {
        case let countdown as Countdown:
            CountdownEditView(isPresented: isPresented, countdown: countdown)
                .environment(\.managedObjectContext, viewContext)
        case let alarm as Alarm:
            AlarmEditView(alarm: alarm, isPresented: isPresented)
                .environment(\.managedObjectContext, viewContext)
        case let stopwatch as Stopwatch:
            StopwatchEditView(isPresented: isPresented, stopwatch: stopwatch)
                .environment(\.managedObjectContext, viewContext)
        default:
            Text("missing edit view")
        }
    }
    
    fileprivate func _launchTimer() {
        
        self.handler?(self.timer)
        
        TimerRouter.performAction(timer: self.timer) { result in
            switch result {
            case .success:
                break
            case .failure(let failure):
                switch failure {
                case TimerRouterError.notificationAuthorizationMissing:
                    self.boringContext.showPermissionAlert = true
                default:
                    self.boringContext.error = failure
                    self.boringContext.showDefaultAlert = true
                }
            }
        }
        
    }
    
}

struct DialView_Previews: PreviewProvider {
    static var previews: some View {
        
        DialView(
            timer: Countdown.fake(context: PersistenceController.preview.container.viewContext),
            isEditingBinding: .constant(true), frameSize: 150.0)
            .environmentObject(Conductor.maestro)
            .environmentObject(BoringContext())

    }
}
