import Adamantium
import AVFoundation

class AdamantiumPresetAuraVideoRender {
    private static let helper = RenderableVideoHelper()

    /** Uses sine based seed loop over the parameter duration */
    static func renderAuraVideoLoop(
        _ colorSet: SunoTriColorSet,
        duration: TimeInterval = 30.0 // in seconds
    ) async throws -> URL {
        let width: Int = 1080
        let height: Int = 1920
        let scale: Float = 1.5

        let noiseRenderable = Simplex3DAuraRenderable()

        func updateNoiseWithSeed(_ seed: Float) {
            noiseRenderable.config = .simpleConfig(
                colorSet: colorSet,
                width: width,
                height: height,
                scale: scale,
                seed: seed
            )
        }

        updateNoiseWithSeed(.zero)
        let renderableLayers: [Renderable] = [
            noiseRenderable,
        ]

        do {
            let framesPerSecond: TimeInterval = 60.0
            let durationInSeconds = duration
            let totalFrameCount: Int = Int(durationInSeconds * framesPerSecond)

            /**
                 Width and height are already taken care of inside of
                 configure and anything set here will be overwritten
                 by the width and height in cofig
             */

            let outputSettings: [String: Any] = [
                AVVideoCodecKey: AVVideoCodecType.hevc,
                AVVideoCompressionPropertiesKey: [
                    AVVideoQualityKey: 0.5,
                ],
            ]

            try helper.configure(
                avOutputSettings: outputSettings,
                width: width,
                height: height,
                frameCount: totalFrameCount,
                framesPerSecond: framesPerSecond,
                renderables: renderableLayers
            )

            let outputURL = try await helper.render { frameInput in
                let noiseSeed: Float = sin(frameInput.completionRatio * 2.0 * .pi) * 0.2
                updateNoiseWithSeed(noiseSeed)
            }

            return outputURL
        } catch {
            throw error
        }
    }
}
