//
//  Heise Vision Pro
//  Copyright © 2024 Gero Gerber. All rights reserved.
//

import ARKit
import RealityKit
import SwiftUI

struct ObjectTrackingView: View {
    @Environment(AppModel.self) private var appModel

    private let root = Entity()
    private let arkitSession = ARKitSession()
    @State private var anchorModels: [UUID: Entity] = .init()

    var body: some View {
        RealityView { content in
            let referenceObjects = Array(appModel.referenceObjects.values)

            content.add(root)

            Task {
                let authorization = await arkitSession.requestAuthorization(for: [.worldSensing])

                guard authorization[.worldSensing] == .allowed else { return }

                let objectTracking = ObjectTrackingProvider(referenceObjects: referenceObjects)

                do {
                    try await arkitSession.run([objectTracking])
                } catch {
                    print(error)
                    return
                }

                for await anchorUpdate in objectTracking.anchorUpdates {
                    switch anchorUpdate.event {
                        case .added:
                            if let model = appModel.referenceObjectModels[anchorUpdate.anchor.referenceObject.id] {
                                var material = PhysicallyBasedMaterial()
                                material.triangleFillMode = .lines
                                material.faceCulling = .back
                                material.baseColor = .init(tint: .green)
                                material.blending = .transparent(opacity: 0.3)

                                model.applyMaterial(material)
                                root.addChild(model)

                                model.transform = Transform(matrix: anchorUpdate.anchor.originFromAnchorTransform)
                                anchorModels[anchorUpdate.anchor.id] = model
                            }
                        case .updated:
                            if let model = anchorModels[anchorUpdate.anchor.id] {
                                model.transform = Transform(matrix: anchorUpdate.anchor.originFromAnchorTransform)
                            }
                        case .removed:
                            if let model = anchorModels[anchorUpdate.anchor.id] {
                                model.removeFromParent()
                                anchorModels.removeValue(forKey: anchorUpdate.anchor.id)
                            }
                    }
                }
            }
        }
        .onDisappear {
            for (_, model) in anchorModels {
                model.removeFromParent()
            }

            anchorModels.removeAll()
        }
    }
}

#Preview(immersionStyle: .full) {
    ObjectTrackingView()
        .environment(AppModel())
}
