//
//  Created by Trulioo Inc. on 2024-05-02.
//

import Foundation
import TruliooCaptureSDK
import React

@objc(TruliooCaptureSdkModule)
class TruliooCaptureSdkModule : RCTEventEmitter {
    private let IMAGE_FEEDBACK_EVENT = "onImageFeedbackResult"
    private var hasListeners = false
    private var activeEvents: [String] = ["onFeedbackStateResult"]
    
    @objc
    func requiresMainQueueSetup() -> Bool {
        return true
    }
    
    override func startObserving() {
        hasListeners = true
    }
    
    override func stopObserving() {
        hasListeners = false
    }
    
    override func supportedEvents() -> [String]! {
        return activeEvents
    }
    
    @objc 
    func initialize(
        _ shortCode: String,
        usePreview: Bool,
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        TruliooCapture().initialize(shortCode, usePreview, TPromise(resolve, reject))
    }

    @objc
    func createCameraComponent(_ configJson: String) {
        do {
            let jsonData = configJson.data(using: .utf8)!
            let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as! [String: Any]
            let cameraId = jsonDict["cameraId"] as! String
            let detectionType = jsonDict["detectionType"] as! Int32
            
            activeEvents.append("\(IMAGE_FEEDBACK_EVENT)-\(cameraId)")
            TruliooCapture().createCameraComponent(cameraId, type: detectionType)
        } catch {
            print("SB [createCameraComponent] exception: \(error.localizedDescription)")
        }
    }

    @objc
    func startFeedbackPromise(
        _ cameraId: String,
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        try! TruliooCapture().addCompletionPromise(cameraId, TPromise(resolve, reject))
    }
    
    @objc
    func captureLatestFrame(
        _ cameraId: String,
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        try! TruliooCapture().manualCapture(TPromise(resolve, reject))
    }
    
    @objc
    func resumeCamera(_ cameraId: String) {
        try! TruliooCapture().resumeCamera(cameraId: cameraId)
    }

    @objc
    func startFeedbackCallback(_ cameraId: String, eventName: String) {
        try! TruliooCapture().addProcessedFrameEvent(cameraId) { feedback in
            self.sendEvent(withName: eventName, body: feedback)
        }
    }
    
    @objc
    func onFeedbackState(_ eventName: String) {
        try! TruliooCapture().addFeedbackStateEvent() { feedback in
            self.sendEvent(withName: eventName, body: feedback)
        }
    }
    
    @objc
    func verifyImage(
        _ imageId: String,
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        try! TruliooCapture().verifyImage(imageId, TPromise(resolve, reject))
    }
    
    @objc
    func acceptImage(
        _ imageId: String,
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        try! TruliooCapture().acceptImage(imageId, TPromise(resolve, reject))
    }
    
    @objc
    func submitTransaction(
        _ resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        let finalResolve: RCTPromiseResolveBlock = { value in
            resolve(value)
            self.stop()
        }
    
        let finalReject: RCTPromiseRejectBlock = { code, message, error in
            reject(code, message, error)
            self.stop()
        }

        TruliooCapture().submitTransaction(TPromise(finalResolve, finalReject))
    }

    @objc
    func stopFeedback(
        _ cameraId: String,
        resolve: @escaping RCTPromiseResolveBlock,
        reject: @escaping RCTPromiseRejectBlock
    ) {
        do {
            try TruliooCapture().stopFeedbackForCamera(cameraId)
            resolve(true)
        } catch {
            print("[NativeModule: stopFeedback ERROR] \(error.localizedDescription)")
            let nsError = NSError(domain: "com.trulioo.docv.capture", code: 401)
            reject("CAMERA_FEEDBACK_ERROR", error.localizedDescription, nsError)
        }
    }

    @objc
    func stop() {
        TruliooCapture().close()
    }
}
