/*
 * Copyright © Dynamsoft Corporation. All rights reserved.
 */

import UIKit
import React
import DynamsoftCaptureVisionBundle

@objc(RNDynamsoftImageSourceAdapter)
public class RNDynamsoftImageSourceAdapter: RCTEventEmitter {

    @objc(createDefaultNativeISA)
    func createDefaultNativeISA() -> String {
        let adapter = ImageSourceAdapter()
        let key = String(adapter.hash)
        DSISAStore.shared.map[key] = adapter
        return key
    }

    @objc func destroy(_ key: String) {
        DSISAStore.shared.map.removeValue(forKey: key)
    }

    @objc(clearBuffer:resolve:reject:)
    func clearBuffer(_ key: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        isa(for: key)?.clearBuffer()
        resolve(nil)
    }

    @objc(getImageCount:resolve:reject:)
    func getImageCount(_ key: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        resolve(isa(for: key)?.imageCount ?? 0)
    }

    @objc(isBufferEmpty:resolve:reject:)
    func isBufferEmpty(_ key: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        resolve(isa(for: key)?.isBufferEmpty ?? true)
    }

    @objc(getColourChannelUsageType:resolve:reject:)
    func getColourChannelUsageType(_ key: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        resolve(isa(for: key)?.colourChannelUsageType.rawValue ?? 0)
    }

    @objc(setColourChannelUsageType:type:resolve:reject:)
    func setColourChannelUsageType(_ key: String, type: NSInteger, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        if let value = ColourChannelUsageType(rawValue: Int(type)) {
            isa(for: key)?.colourChannelUsageType = value
        }
        resolve(nil)
    }

    @objc(getMaximumImageCount:resolve:reject:)
    func getMaximumImageCount(_ key: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        resolve(isa(for: key)?.maxImageCount ?? 0)
    }

    @objc(setMaximumImageCount:maxCount:resolve:reject:)
    func setMaximumImageCount(_ key: String, maxCount: NSInteger, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
        isa(for: key)?.maxImageCount = UInt(maxCount)
        resolve(nil)
    }

    @objc(setNextImageToReturn:imageId:resolver:rejecter:)
    func setNextImageToReturn(_ key: String, imageId: NSInteger, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
        isa(for: key)?.setNextImageToReturn(imageId, keepInBuffer: true)
        resolve(true)
    }

    @objc func startFetching(_ key: String) {
        isa(for: key)?.startFetching()
    }

    @objc func stopFetching(_ key: String) {
        isa(for: key)?.stopFetching()
    }

    @objc(hasImage:imageId:)
    func hasImage(_ key: String, imageId: NSInteger) -> NSNumber {
        return NSNumber(value: isa(for: key)?.hasImage(imageId) ?? false)
    }

    // MARK: - Private

    private func isa(for key: String) -> ImageSourceAdapter? {
        return DSISAStore.shared.map[key] as? ImageSourceAdapter
    }

    // Invoked from the JSI installer (RNDynamsoftImageSourceAdapterJSI.mm).
    @objc(addImage:toISA:)
    public func addImage(_ data: ImageData, toISA key: String) {
        isa(for: key)?.addImageToBuffer(data)
    }

    // Invoked from the JSI installer (RNDynamsoftImageSourceAdapterJSI.mm).
    @objc(imageDataFromISA:)
    public func imageDataFromISA(_ key: String) -> ImageData? {
        return isa(for: key)?.getImage()
    }
}
