//
//  NewCountdownView.swift
//  LeCountdown
//
//  Created by Laurent Morvillier on 20/01/2023.
//

import SwiftUI
import CoreData
import WidgetKit

struct NewCountdownView : View {
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @Binding var isPresented: Bool

    var body: some View {
        CountdownEditView(isPresented: $isPresented)
            .environment(\.managedObjectContext, viewContext)
            .navigationTitle("New countdown")
    }
    
}

struct CountdownEditView : View {
    
    @Environment(\.managedObjectContext) private var viewContext
    @Environment(\.dismiss) private var dismiss
    
    @StateObject var model: TimerModel = TimerModel()

    var countdown: Countdown? = nil
    var preset: Preset? = nil

    @Binding var isPresented: Bool
    
    @State var secondsString: String = ""
    @State var minutesString: String = ""
    @State var nameString: String = ""

    @State var soundRepeatCount: Int16 = 0
    @State var image: CoolPic = .pic1

    @State var deleteConfirmationShown: Bool = false
    @State var activityNameConfirmationShown: Bool = false
    @State fileprivate var _rename: Bool? = nil

    @State var errorShown: Bool = false
    @State var error: Error? = nil
    
    var tabSelection: Binding<Int>? = nil
    
//    @FocusState private var textFieldIsFocused: Bool

    @FetchRequest(sortDescriptors: [])
    private var timers: FetchedResults<AbstractTimer>
    
    @State var _isNewCountdown: Bool = false // false if editing an existing countdown
    @State var _hasLoaded = false
    
    @Environment(\.isPresented) var envIsPresented

    init(isPresented: Binding<Bool>, countdown: Countdown? = nil) {
        _isPresented = isPresented
        self.countdown = countdown
    }
    
    init(isPresented: Binding<Bool>, preset: Preset, tabSelection: Binding<Int>) {
        _isPresented = isPresented
        self.preset = preset
        self.tabSelection = tabSelection
    }
    
    var body: some View {
        NavigationStack {
            Rectangle()
                .frame(width: 0.0, height: 0.0)
                .onChange(of: envIsPresented) { newValue in
                    if !newValue && !self._isNewCountdown {
                        self._save() // save when leaving an edit screen
                    }
                }
            CountdownFormView(
                secondsBinding: $secondsString,
                minutesBinding: $minutesString,
                nameBinding: $nameString,
                imageBinding: $image,
                repeatCountBinding: $soundRepeatCount)
                .environmentObject(self.model)
            .onAppear {
                self._onAppear()
            }
            .confirmationDialog("", isPresented: $deleteConfirmationShown, actions: {
                Button("Yes", role: .destructive) {
                    withAnimation {
                        self._delete()
                    }
                }.keyboardShortcut(.defaultAction)
                Button("No", role: .cancel) {}
            }, message: {
                Text("Do you really want to delete?")
            })
            .confirmationDialog("", isPresented: $activityNameConfirmationShown, actions: {
                Button("Rename") {
                    self._rename = true
                    self._save()
                }
                Button("New activity") {
                    self._rename = false
                    self._save()
                }
            }, message: {
                Text("Do you wish to rename or create a new activity")
            })

            .alert("", isPresented: $errorShown, actions: { }, message: {
                Text(error?.localizedDescription ?? "error")
            })
            .toolbar {
                if self._isNewCountdown {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Button("Cancel") {
                            self._cancel()
                        }
                    }
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button("Save") {
                            self._save()
                        }
                    }
                } else {
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button {
                            self.deleteConfirmationShown = true
                        } label: {
                            Image(systemName: "trash")
                        }
                    }
                }
            }
            .navigationTitle("Edit countdown")
        }
        
    }
    
    // MARK: - Business

    fileprivate func _onAppear() {
        
        self._isNewCountdown = (self.countdown == nil)
        if !self._hasLoaded {
            if let countdown {
                self._loadCountdown(countdown)
            } else if let preset {
                self._loadPreset(preset)
            }
            self._hasLoaded = true
        }
        
    }
    
    fileprivate func _loadPreset(_ preset: Preset) {
        self.nameString = preset.localizedName
        
        let nf = NumberFormatter()
        let minutes = Int(preset.duration / 60.0)
        if minutes > 0 {
            self.minutesString = nf.string(from: NSNumber(value: minutes)) ?? ""
        }
        
        let seconds = Int(preset.duration) - minutes * 60
        if seconds > 0 {
            self.secondsString = nf.string(from: NSNumber(value: seconds)) ?? ""
        }
        
        self.model.group = preset.intervalGroup
        self.model.sounds = preset.sound

    }
    
    fileprivate func _loadCountdown(_ countdown: Countdown) {
        
        let minutes = Int(countdown.duration / 60.0)
        let seconds = countdown.duration - Double(minutes * 60)
        
        if minutes > 0 {
            self.minutesString = self._numberFormatter.string(from: NSNumber(value: minutes)) ?? ""
        }
        
        if seconds > 0 {
            self.secondsString = self._numberFormatter.string(from: NSNumber(value: seconds)) ?? ""
        }
        
        if let name = countdown.activity?.name, !name.isEmpty {
            self.nameString = name
        }
        
        self.model.sounds = countdown.sounds
        
        //            if let sound = Sound(rawValue: Int(countdown.sound)) {
        //                self.sound = sound
        //            }
        self.soundRepeatCount = countdown.repeatCount
        
        if let image = countdown.image, let coolpic = CoolPic(rawValue: image) {
            self.image = coolpic
        }
    }
    
    fileprivate let _numberFormatter = NumberFormatter()
    
    fileprivate var _seconds: Double {
        return self._numberFormatter.number(from: self.secondsString)?.doubleValue ?? 0.0
    }
    
    fileprivate var _minutes: Double {
        return self._numberFormatter.number(from: self.minutesString)?.doubleValue ?? 0.0
    }
    
    fileprivate func _cancel() {
        viewContext.rollback()
        self.isPresented = false
    }
    
    fileprivate func _save() {
        
        let cd: Countdown
        if let countdown {
            cd = countdown
        } else {
            cd = Countdown(context: viewContext)
        }
        
        cd.duration = self._minutes * 60.0 + self._seconds
        if self._isNewCountdown {
            let max: Int16
            if let maxOrder = self.timers.map({ $0.order }).max() {
                max = maxOrder + 1
            } else {
                max = 0
            }
            cd.order = max
        }
        
        cd.image = self.image.rawValue
        cd.setSounds(self.model.sounds)
        
//        cd.setPlaylists(self.playlists)
        cd.repeatCount = self.soundRepeatCount
        
        if !self.nameString.isEmpty {
            
            let trimmed = self.nameString.trimmingCharacters(in: .whitespacesAndNewlines)
            
            if let activity = cd.activity, let currentActivityName = activity.name, trimmed != currentActivityName {
                
                switch self._rename {
                case .none:
                    self.activityNameConfirmationShown = true
                    return
                case .some(let rename):
                    if rename {
                        activity.name = trimmed
                    } else {
                        cd.activity = CoreDataRequests.getOrCreateActivity(name: trimmed)
                    }
                }
            } else {
                cd.activity = CoreDataRequests.getOrCreateActivity(name: trimmed)
            }
            
        }
        
        self._saveContext()
        
        WidgetCenter.shared.reloadAllTimelines() // refreshes the visual of existing widgets
        
        self._popOrDismiss()
    }
    
    fileprivate func _popOrDismiss() {
        if self._isNewCountdown {
            self.isPresented = false
        } else {
            dismiss()
        }
        
        if self.preset != nil {
            self.tabSelection?.wrappedValue = 1
        }
        
    }
    
    fileprivate func _delete() {
        
        guard let countdown else {
            return
        }
        
        viewContext.delete(countdown)
        self._saveContext()

        WidgetCenter.shared.reloadAllTimelines() // refreshes the visual of existing widgets

        self._popOrDismiss()
    }
    
    fileprivate func _saveContext() {
        do {
            try viewContext.save()
        } catch {
            Logger.error(error)
            self.errorShown = true
            self.error = error
        }
    }
    
}

struct NewCountdownView_Previews: PreviewProvider {
    static var previews: some View {
        NewCountdownView(isPresented: .constant(true))
            .environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}
