
import Foundation
import CoreImage

public class ImageUtility {
    
    enum ImageUtilityError: Error {
        case couldNotCreatePixelBuffer
    }
    
    public static func ciImage(_ url: URL?) -> CIImage? {
        guard
            let imageURL = url,
            let ciImage = CIImage(contentsOf: imageURL)
        else { return nil }
        return ciImage
    }
    
    public init() { }

    static func ciImageToCVPixelBuffer(_ ciImage: CIImage, size: CGSize) -> CVPixelBuffer? {
        var pixelBuffer: CVPixelBuffer?
        
        // Pixel buffer options
        let options: [String: Any] = [
            kCVPixelBufferCGImageCompatibilityKey as String: true,
            kCVPixelBufferCGBitmapContextCompatibilityKey as String: true
        ]
        
        // Create pixel buffer
        let status = CVPixelBufferCreate(
            kCFAllocatorDefault,
            Int(size.width),
            Int(size.height),
            kCVPixelFormatType_32ARGB,
            options as CFDictionary,
            &pixelBuffer)
        
        guard status == kCVReturnSuccess, let buffer = pixelBuffer else {
            print("Error creating pixel buffer")
            return nil
        }
        
        // Lock the pixel buffer memory so it can be rendered into
        CVPixelBufferLockBaseAddress(buffer, [])
        
        // Create a CIContext for rendering
        let context = CIContext()
        
        // Render the CIImage into the pixel buffer
        context.render(ciImage, to: buffer)
        
        // Unlock the pixel buffer
        CVPixelBufferUnlockBaseAddress(buffer, [])
        
        return buffer
    }
    
    static func createPixelPuffer(size: CGSize) throws -> CVPixelBuffer? {
        
        var pixelBuffer: CVPixelBuffer?
        
        // Pixel buffer options
        let options: [String: Any] = [
            kCVPixelBufferCGImageCompatibilityKey as String: true,
            kCVPixelBufferCGBitmapContextCompatibilityKey as String: true
        ]
        
        // Create pixel buffer
        let status = CVPixelBufferCreate(
            kCFAllocatorDefault,
            Int(size.width),
            Int(size.height),
            kCVPixelFormatType_32ARGB,
            options as CFDictionary,
            &pixelBuffer)
        
        guard status == kCVReturnSuccess, let buffer = pixelBuffer else {
            throw ImageUtilityError.couldNotCreatePixelBuffer
        }
        
        return buffer
    }
}
