//
//  ScanQRFile.swift
//  react-native-barcode-scanner
//
//  Created by TDV on 03/08/2023.
//

import Foundation
import AVFoundation
import Vision
import React

@objc(ScanQRFile)
class ScanQRFile: NSObject {
    @objc
    static func requiresMainQueueSetup() -> Bool {
        return true
    }
    
    @objc func scan(_ imagePath: String,
                    resolver resolve: @escaping RCTPromiseResolveBlock,
                    rejecter reject: @escaping RCTPromiseRejectBlock) {
        // Convert the image URI to a valid file URL
        guard let imageUrl = URL(string: imagePath) else {
            reject("INVALID_URL", "The provided image URI is invalid.", nil)
            return
        }
        
        // Check if the file exists
        if !FileManager.default.fileExists(atPath: imageUrl.path) {
            reject("IMAGE_NOT_FOUND", "The image file could not be found.", nil)
            return
        }
        
        // Load the image from the URL
        guard let originalImage = UIImage(contentsOfFile: imageUrl.path) else {
            reject("IMAGE_LOAD_FAILED", "Failed to load the image.", nil)
            return
        }
        
        // Define the target size for the resized image (adjust as needed)
        let targetSize = CGSize(width: 800, height: 600) // You can change the dimensions
        
        // Calculate the new size while preserving the original aspect ratio
        let newSize = AVMakeRect(aspectRatio: originalImage.size, insideRect: CGRect(origin: CGPoint.zero, size: targetSize)).size
        
        // Resize the image
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        originalImage.draw(in: CGRect(origin: CGPoint.zero, size: newSize))
        let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        // Ensure we have a valid resized image
        guard let image = resizedImage else {
            reject("IMAGE_RESIZE_FAILED", "Failed to resize the image.", nil)
            return
        }

        let request = VNDetectBarcodesRequest { request, error in
            if let error = error {
                reject("BARCODE_SCAN_FAILED", "Failed to scan barcode.", error)
            } else {
                guard let results = request.results as? [VNBarcodeObservation], let barcode = results.first else {
                    reject("BARCODE_NOT_FOUND", "No barcode found in the image.", nil)
                    return
                }
                                
                let barcodePayload = barcode.payloadStringValue ?? ""
                resolve(barcodePayload)
            }
        }
        
        let handler = VNImageRequestHandler(cgImage: image.cgImage!, options: [:])
        do {
            try handler.perform([request])
        } catch {
            reject("IMAGE_LOAD_FAILED", "Failed to load the image.", error)
        }
    }
}

