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

import SwiftUI
import CoreData
import BackgroundTasks
import AVFoundation
import Combine

@main
struct LeCountdownApp: App {
    
    let persistenceController = PersistenceController.shared
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    init() {
        UITabBar.appearance().backgroundColor = UIColor(white: 0.96, alpha: 1.0)
        
        UIPageControl.appearance().currentPageIndicatorTintColor = .systemPink
        UIPageControl.appearance().pageIndicatorTintColor = UIColor(white: 0.7, alpha: 1.0)
        
        self._registerBackgroundRefreshes()
        self._initSchema()
        
    }
    
    fileprivate func _initSchema() {
        
        do {
            try persistenceController.container.initializeCloudKitSchema()
        } catch {
            print("ERROR \(error)")
        }
        
    }
    
    @Environment(\.scenePhase) var scenePhase
    
    var body: some Scene {
        
        WindowGroup {
            Group {
                #if os(iOS)
                
                if UIDevice.isPhoneIdiom {
                    CompactHomeView()
                        .environment(\.managedObjectContext, persistenceController.container.viewContext)
                } else {
                    RegularHomeView()
                        .environment(\.managedObjectContext, persistenceController.container.viewContext)
                }
                #else
                RegularHomeView()
                    .environment(\.managedObjectContext, persistenceController.container.viewContext)
                #endif
            }
//            .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
//                self._willEnterForegroundNotification()
//            }
            .onAppear {
                self._onAppear()
            }
            .onChange(of: scenePhase) { newPhase in
                switch newPhase {
                case .inactive:
                    Conductor.maestro.stopMainPlayersIfPossible()
                case .active:
                    Logger.log("onChange(of: scenePhase) active")
                    Logger.log(Conductor.maestro.currentCountdowns.count)
                    Conductor.maestro.restore()
                    Conductor.maestro.cleanup()
                default:
                    break
                }
            }
        }

    }
    
    fileprivate func _onAppear() {
        
        Logger.log("preferredLanguages = \(String(describing: Locale.preferredLanguages))")
        
        Sound.computeSoundDurationsIfNecessary()
        
        self._patch()
        
//        let voices = AVSpeechSynthesisVoice.speechVoices()
//        let grouped = Dictionary(grouping: voices, by: { $0.language })
//        for language in grouped.keys {
//            if let lvoices = grouped[language] {
//                print("language = \(language)")
//                for voice in lvoices {
//                    print("name = \(voice.name), gender = \(voice.gender)")
//                }
//                print("========")
//            }
//        }
        
    }
    
    fileprivate func _registerBackgroundRefreshes() {
        BGTaskScheduler.shared.register(forTaskWithIdentifier: BGTaskIdentifier.refresh.rawValue, using: nil) { task in
             self._handleAppRefresh(task: task as! BGAppRefreshTask)
        }
    }
    
    fileprivate func _handleAppRefresh(task: BGAppRefreshTask) {
        
        print("_handleAppRefresh = \(task.description)")
        
        task.expirationHandler = {
            print("expired")
        }
        
        DispatchQueue.main.async {
            Conductor.maestro.updateLiveActivities()
            task.setTaskCompleted(success: true)
        }
        
    }
    
    
    fileprivate func _patch() {
        
        let context = PersistenceController.shared.container.viewContext
        do {
            let records = try context.fetch(Record.fetchRequest())
            for record in records {
                record.preCompute()
            }
            try context.save()
        } catch {
            Logger.error(error)
        }
        
    }
    
}
