//
//  SailassistApp.swift
//  Sailassist
//
//  Created by Mamoru Sugita on 2023/10/13.
//

import SwiftUI
import UserNotifications
import WindowsAzureMessaging

@main
struct SailassistApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @State var isAgree = Preferences.termsAgreeDate != nil

    var body: some Scene {
        WindowGroup {
            if isAgree {
                ContentView()
            }else{
                VStack(spacing: 0){
                    WebView(isLoading: .constant(false), url: HttpRequestType.Terms.rawValue)
                    
                    Button(action: {
                        Preferences.termsAgreeDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
                        isAgree = true
                    }, label: {
                        Text("Accept")
                            .frame(maxWidth: .infinity)
                            .padding(.vertical, 10)
                            .border(ColorSet.LineColor04.color, width: 1, cornerRadius: 5)

                    })
                    .padding()
                    .background(ColorSet.BackgroundPrimary.color)
                }
                .preferredColorScheme(.dark)

            }
        }
    }
}

//class notificationTags: NSObject {
//    func addTags() {
//        if Preferences.shipId != 0 {
//            let shipId = String(Preferences.shipId)
//            let testTag = "aaa"
//            let routeTag = "route-" + shipId
//            let bamTag = "bam-" + shipId
//            let taskAlertTag = "taskalert-" + shipId
//            let sailassistTag = "sailassist-" + shipId
//            MSNotificationHub.addTags([testTag, routeTag, bamTag, taskAlertTag, sailassistTag])
//        }
//    }
//}

class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, MSInstallationLifecycleDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print(debug: "called")

        //プッシュ通知の利用許可のリクエスト送信
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
            if error != nil {
                return
            }
            if granted {
                MSNotificationHub.setLifecycleDelegate(self)
                UNUserNotificationCenter.current().delegate = self
                MSNotificationHub.setDelegate(self)

                MSNotificationHub.start(connectionString: HttpRequestType.ConnectionString.rawValue, hubName: HttpRequestType.HubName.rawValue)
                self.addTags()
            }
        }
        application.registerForRemoteNotifications()

        return true
    }

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        print(debug: "called")
        let config = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
        config.delegateClass = SceneDelegate.self
        return config
    }

    func addTags() {
        if Preferences.shipId != 0 {
            let shipId = String(Preferences.shipId)
//            let shipId = "10000083"
            let routeTag = "route-" + shipId
            let bamTag = "bam-" + shipId
            let taskAlertTag = "taskalert-" + shipId
            let sailassistTag = "sailassist-" + shipId
            MSNotificationHub.addTags([routeTag, bamTag, taskAlertTag, sailassistTag])
            MSNotificationHub.addTags([routeTag])
        }
    }

    // Push通知を受信した時（サイレントプッシュ）
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print(debug: "called \(userInfo)")

        // Forward to MSNotificationHub
        MSNotificationHub.didReceiveRemoteNotification(userInfo)

        // Complete handling the notificationposition
        completionHandler(.noData)

        let message = GetMessage()
        message.start()

        let route = MonitoringRoute()
        route.start()

        let ecaList = GetEcaList()
        ecaList.start()

        let pushHistory = GetPushHistory()
        pushHistory.start()

//        guard let data = userInfo["data"] as? [String: Any],
//                let newTitle = data["newTitle"] as? String,
//                let newBody = data["newBody"] as? String else {
//            completionHandler(.noData)
//            return
//        }
//        // ローカル通知で表示するタイトルとメッセージを変更する
//        showLocalNotification(identifier: "SilentPush", title: newTitle, body: newBody)
//        completionHandler(.newData)
    }

    func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification notification: MSNotificationHubMessage!) {

        let title = notification.title ?? ""
        let body = notification.body ?? ""

        if (UIApplication.shared.applicationState == .background) {
            print("Notification received in background: title:\"\(title)\" body:\"\(body)\"")
        } else {
            let alertController = UIAlertController(title: title, message: body, preferredStyle: .alert)
            alertController.addAction(UIAlertAction(title: "OK", style: .cancel))

            //            self.present(alertController, animated: true)
        }
    }

    // APNs 登録成功時に呼ばれる
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
        print("デバイストークン : \(token)")
    }

    // APNs 登録失敗時に呼ばれる
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("APNs 登録に失敗しました : \(error.localizedDescription)")
    }
}

extension AppDelegate: UNUserNotificationCenterDelegate {
    // フォアグラウンド状態で通知を受信して表示する
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                              willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        print(debug: userInfo)
        if !userInfo.isEmpty {
            guard let senTypeStr = userInfo["sendType"] as? String else {
                completionHandler([.badge, .sound, .banner, .list])
                return
            }
//            switch PushNotificationTypes.SendType(Int32(sendTypeStr) ?? -1){
//            case .NewChatMessage:
//                //foreground時、通知の内容種別がチャットなら通知を表示しない
//                let semaphore = DispatchSemaphore(value: 0)
//                SessionManager().prepareSession(semaphore: semaphore)
//                let sessionGetWatchingApp = SessionGetWatchingApp()
//                let sessionGetWatcherApp = SessionGetWatcherApp()
//
//                DispatchQueue(label: "WebAppRequest").async {
//                    semaphore.wait()
//                    sessionGetWatchingApp.ErrCnt = 0
//                    sessionGetWatchingApp.RequestGetWatchingApp("arrivedChatPush")
//
//                    sessionGetWatcherApp.ErrCnt = 0
//                    sessionGetWatcherApp.RequestGetWatcherApp("arrivedChatPush")
//                }
//                completionHandler([])
//                return
//            default:
//                break
//            }
        }
        completionHandler([[.banner, .badge, .sound]])
    }

    // バックグラウンド状態で通知を受信して表示する
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                              didReceive response: UNNotificationResponse,
                              withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        print(debug: userInfo)

        if let custom = userInfo["key"] as? String {
            print(debug: "called \(custom)")

            if custom == "map" {

            }
        }
        completionHandler()
    }
}

class SceneDelegate: UIResponder, UIWindowSceneDelegate, ObservableObject {
    weak var windowScene: UIWindowScene?
    var tabWindow: UIWindow?
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        windowScene = scene as? UIWindowScene
    }
    
    
    func addTabBar(_ selectedTabModel: SelectedTabModel){
        guard let scene = windowScene else{
            return
        }
        
        let tabBarController = UIHostingController(rootView:
            CustomTabBar()
                .environmentObject(selectedTabModel)
                .frame(maxHeight: .infinity, alignment: .bottom)
        )
        
        tabBarController.view.backgroundColor = .clear
        
        let tabWindow = PassThroughWindow(windowScene: scene)
        tabWindow.rootViewController = tabBarController
        tabWindow.isHidden = false
        
        self.tabWindow = tabWindow
    }
}


class PassThroughWindow: UIWindow{
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard let view = super.hitTest(point, with: event) else { return nil}
        return rootViewController?.view == view ? nil : view
    }
}

// MARK: コメント出力を消す
func print(debug: Any = "", function: String = #function, file: String = #file, line: Int = #line) {
    #if DEBUG
        var filename: NSString = file as NSString
        filename = filename.lastPathComponent as NSString
        // Swift.print("File: \(filename), Line: \(line), Func: \(function) \n\(debug)")

        let outstr = String( format: "APPDebug File: %@, Line: %d, Func: %@\n\(debug)", filename, line, function )
        // Swift.print( outstr ) NSLog がある時は、両方に出るのでいらない
        NSLog( outstr )     // デバッグコンソールにも出力
    #endif
}
