import CoreMedia
import Metal
import MetalKit
import SwiftUI

struct PreviewMetalViewRepresentable: UIViewRepresentable {
    
    @ObservedObject var videoCaptureCoordinator: VideoCaptureCoordinator
    @ObservedObject var audioCaptureCoordinator: AudioCaptureCoordinator
    @ObservedObject var previewCoordinator: PreviewMetalViewCoordinator
    
    @Binding var uniformScale: CGFloat
    
    init(videoCaptureCoordinator: VideoCaptureCoordinator,
         audioCaptureCoordinator: AudioCaptureCoordinator,
         previewCoordinator: PreviewMetalViewCoordinator,
         uniformScale: Binding<CGFloat>) {
        
        self.videoCaptureCoordinator = videoCaptureCoordinator
        self.audioCaptureCoordinator = audioCaptureCoordinator
        self.previewCoordinator = previewCoordinator
        self._uniformScale = uniformScale
    }
    
    func makeCoordinator() -> VideoCaptureCoordinator {
        return videoCaptureCoordinator
    }
    
    func makeUIView(context: Context) -> PreviewMetalView {
        let metalView = PreviewMetalView()
        
        // Preview Coordinator
        metalView.previewCoordinator = previewCoordinator
        previewCoordinator.previewMetalView = metalView
        
        return metalView
    }
    
    func updateUIView(_ uiView: PreviewMetalView, context: Context) {
        previewCoordinator.setPassthroughScale(uniformScale)
    }
}

class PreviewMetalView: MTKView {
    weak var previewCoordinator: PreviewMetalViewCoordinator?
    
    init() {
        super.init(frame: .zero, device: Adamantium.sharedDevice)
        colorPixelFormat = .bgra8Unorm
        framebufferOnly = false
        
        // This is the default but just so it is completely obvious
        preferredFramesPerSecond = 60
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func draw(_ rect: CGRect) {
        previewCoordinator?.draw(
            rect,
            bounds: bounds,
            drawable: currentDrawable,
            renderPassDescriptor: currentRenderPassDescriptor)
    }
}
