import Foundation
import Metal

protocol RequiresBackgroundTexture {
    var backgroundTexture: MTLTexture? { get set }
}

public class OfflineRenderHelper {
    public var lastRender: MTLTexture?
    
    private let width: Int
    private let height: Int
    
    public init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
    
    public func commitRenderableLayers(layers: [Renderable]) {
        let config: OfflineMultiLayerRender.Config
        config = .init(pixelFormat: .bgra8Unorm,
                       clearColor: MTLClearColorMake(0.0, 0.0, 0.0, 0.0),
                       width: width,
                       height: height)

        for renderable in layers {
            let offlineRender = OfflineMultiLayerRender()
            offlineRender.delegate = self
            offlineRender.begin(config: config)
            offlineRender.draw(renderable: renderable)
            offlineRender.commit()
        }
    }
    
    public func chooseBackground(layers: inout [Renderable], color: ADVector3 = .white) {
        let colorFill = ColorFillRenderable()
        colorFill.config = .init(color: color)
        layers.append(colorFill)
    }
    
    public func getRenderableArrayWithBackground(color: ADVector3 = .white) -> [Renderable] {
        let colorFill = ColorFillRenderable()
        colorFill.config = .init(color: color)
        return [colorFill]
    }
    
    public func clearLastRender() {
        lastRender = nil
    }
}

extension OfflineRenderHelper: OfflineMultiLayerRenderDelegate {
    public func finishedRenderingOffline(_ render: MTLTexture) {
        lastRender = render
    }

    public func performPreRenderActionOnEncoder(
        _ encoder: MTLRenderCommandEncoder, renderable: Renderable) {
            
        var mutableRender = renderable as? RequiresBackgroundTexture
        guard let _ = mutableRender else { return }
        mutableRender?.backgroundTexture = lastRender
    }
}
