import Foundation
import CoreGraphics
import ImageIO
import CryptoKit

public struct ImageInput {
    public let image: CGImage
    public let sha256: String
    public static func load(url: URL) throws -> Self {
        guard let source = CGImageSourceCreateWithURL(url as CFURL, nil),
              let properties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [CFString: Any],
              let width = properties[kCGImagePropertyPixelWidth] as? Int,
              let height = properties[kCGImagePropertyPixelHeight] as? Int,
              width > 0, height > 0, width <= 16000, height <= 16000,
              width * height <= 40_000_000 else { throw PoseError.invalidInput("Unreadable image or exceeds 40 megapixel limit.") }
        let options: [CFString: Any] = [kCGImageSourceCreateThumbnailFromImageAlways: true,
            kCGImageSourceCreateThumbnailWithTransform: true, kCGImageSourceThumbnailMaxPixelSize: max(width, height)]
        guard let image = CGImageSourceCreateThumbnailAtIndex(source, 0, options as CFDictionary) else {
            throw PoseError.invalidInput("Unable to normalize image orientation.")
        }
        let digest = try SHA256.hash(data: Data(contentsOf: url)).map { String(format: "%02x", $0) }.joined()
        return Self(image: image, sha256: digest)
    }
    public func cropped(to rect: PixelRect) throws -> CGImage {
        try rect.validate(imageWidth: image.width, imageHeight: image.height)
        guard let result = image.cropping(to: CGRect(x: rect.x, y: rect.y, width: rect.width, height: rect.height)) else {
            throw PoseError.invalidInput("Unable to crop image.")
        }
        return result
    }
}
