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(_: 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
    }

    @available(*, unavailable)
    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
        )
    }
}
