import Foundation
import UIKit
import ScanbotSDKNativeWrapper

@objc
public class RNScanbotDocumentScannerViewController: UIViewController  {
    
    private let defaults = DocumentScannerDefaultValues()
    private var scannerViewController: SBSDKDocumentScannerViewController = SBSDKDocumentScannerViewController()
    @objc public var delegate: SBSDKDocumentScannerViewControllerDelegate?
    
    public override func viewDidLoad() {
        super.viewDidLoad()
        
        self.sbsdk_attach(scannerViewController, in: self.view)
        scannerViewController.delegate = delegate
    }
    
    //MARK: Defaults
    private func setBehaviorDefaults(){
        scannerViewController.hideSnapButton = true
        scannerViewController.suppressDetectionStatusLabel = true
        scannerViewController.suppressPolygonLayer = !defaults.polygonEnabled
        
        scannerViewController.acceptedAngleScore = defaults.acceptedAngleScore
        scannerViewController.acceptedBrightnessThreshold = defaults.acceptedBrightnessThreshold
        scannerViewController.acceptedSizeScore = defaults.acceptedSizeScore
        scannerViewController.autoSnappingMode = defaults.autoSnappingEnabled
        scannerViewController.autoSnappingSensitivity = CGFloat(defaults.autoSnappingSensitivity)
        scannerViewController.autoSnappingDelay = defaults.autoSnappingDelay
        scannerViewController.ignoreBadAspectRatio = defaults.ignoreBadAspectRatio
    }
    
    private func finderConfigDefaults() -> SBSDKBaseScannerViewFinderConfiguration {
        let config = SBSDKBaseScannerViewFinderConfiguration()
        config.isViewFinderEnabled = defaults.finderEnabled
        config.lineWidth = CGFloat(defaults.finderLineWidth)
        config.minimumInset = defaults.finderMinimumPadding
        config.lineColor = defaults.finderLineColor
        config.backgroundColor = defaults.finderOverlayColor
        config.aspectRatio = defaults.finderAspectRatio
        return config
    }
    
    private func setPolygonConfigDefaults(config: SBSDKDocumentScannerPolygonConfiguration){
        config.strokeWidth = defaults.polygonLineWidth
        config.cornerRadius = defaults.finderCornerRadius
        config.fillColor = defaults.polygonBackgroundColor
        config.strokeColor = defaults.polygonColor
    }
    
    private func setPolygonOKConfigDefaults(config: SBSDKDocumentScannerPolygonConfiguration){
        config.strokeWidth = defaults.polygonLineWidth
        config.cornerRadius = defaults.finderCornerRadius
        config.fillColor = defaults.polygonBackgroundColorOK
        config.strokeColor = defaults.polygonColorOK
    }
    
    private func setAutoSnappingPolygonConfigDefaults(config: SBSDKDocumentScannerPolygonConfiguration){
        config.enabled = defaults.polygonAutoSnapProgressEnabled
        config.strokeWidth = defaults.polygonLineWidth
        config.cornerRadius = defaults.finderCornerRadius
        config.fillColor = defaults.polygonBackgroundColorOK
        config.strokeColor = defaults.polygonAutoSnapProgressColor
    }
    
    @objc
    public func setDefaults(){
        setBehaviorDefaults()
        scannerViewController.viewFinderConfiguration = finderConfigDefaults()
        setPolygonConfigDefaults(config: scannerViewController.polygonConfigurationRejected)
        setPolygonOKConfigDefaults(config: scannerViewController.polygonConfigurationAccepted)
        setAutoSnappingPolygonConfigDefaults(config: scannerViewController.autoSnapProgressPolygonConfiguration)
    }
    
    //MARK: Properties
    
    @objc
    public func acceptedAngleScore(_ value: NSNumber?){
        scannerViewController.acceptedAngleScore = value?.doubleValue ?? defaults.acceptedAngleScore
    }
    
    @objc
    public func acceptedBrightnessThreshold(_ value: NSNumber?){
        scannerViewController.acceptedBrightnessThreshold = value?.intValue ?? defaults.acceptedBrightnessThreshold
    }
    
    @objc
    public func acceptedSizeScore(_ value: NSNumber?){
        scannerViewController.acceptedSizeScore = value?.doubleValue ?? defaults.acceptedSizeScore
    }
    
    @objc
    public func autoSnappingEnabled(_ value: Bool){
        scannerViewController.autoSnappingMode = value ? SBSDKAutoSnappingMode.enabled : SBSDKAutoSnappingMode.disabled
    }
    
    @objc
    public func autoSnappingSensitivity(_ value: NSNumber?){
        scannerViewController.autoSnappingSensitivity = CGFloat(value?.floatValue ?? defaults.autoSnappingSensitivity)
    }
    
    @objc
    public func autoSnappingDelay(_ value: NSNumber?){
        scannerViewController.autoSnappingDelay = value?.doubleValue ?? defaults.autoSnappingDelay
    }
    
    @objc
    public func cameraModule(_ value: NSString?){
        var cameraModule: SBSDKCameraDevice? = defaults.cameraModule
        
        if let value = value as? String, let device = SBSDKCameraDevice.fromString(value) {
            cameraModule = device
        }
        
        if let cameraModule {
            scannerViewController.cameraDevice = cameraModule
        }
        
    }
    
    @objc
    public func cameraPreviewMode(_ value: NSString?){
        if let previewMode = SBComponentUtils.decodeFromString(type: SBSDKVideoContentMode.self, value: value as String?) {
            scannerViewController.generalConfiguration.videoContentMode = previewMode
        } else {
            scannerViewController.generalConfiguration.videoContentMode = defaults.cameraPreviewMode
        }
        scannerViewController.withGeneralConfigCopy()
    }
    
    @objc
    public func flashEnabled(_ value: Bool){
        scannerViewController.isFlashLightEnabled = value
    }
    
    @objc
    public func ignoreBadAspectRatio(_ value: Bool){
        scannerViewController.ignoreBadAspectRatio = value
    }
    
    @objc
    public func photoQualityPrioritization(_ value: NSString?){
        if let quality = SBComponentUtils.decodeFromString(type: SBSDKCapturePhotoQualityPrioritization.self, value: value as String?) {
            scannerViewController.generalConfiguration.photoQualityPrioritization = quality
        } else {
            scannerViewController.generalConfiguration.photoQualityPrioritization = defaults.photoQualityPrioritization
        }
        scannerViewController.withGeneralConfigCopy()
    }
    
    @objc
    public func requiredAspectRatios(_ value: NSArray?){
        scannerViewController.requiredAspectRatios = SBSDKAspectRatio.fromArray(value as? [[String : Any]])
    }
    
    @objc
    public func finderEnabled(_ value: Bool){
        scannerViewController.viewFinderConfiguration.isViewFinderEnabled = value
        scannerViewController.withFinderCopy()
    }
    
    @objc
    public func finderLineColor(_ value: UIColor?){
        scannerViewController.viewFinderConfiguration.lineColor = value ?? defaults.finderLineColor
        scannerViewController.withFinderCopy()
    }
    
    @objc
    public func finderLineWidth(_ value: NSNumber?){
        scannerViewController.viewFinderConfiguration.lineWidth = CGFloat(value?.floatValue ?? defaults.finderLineWidth)
        scannerViewController.withFinderCopy()
    }
    
    @objc
    public func finderOverlayColor(_ value: UIColor?){
        scannerViewController.viewFinderConfiguration.backgroundColor = value ?? defaults.finderOverlayColor
        scannerViewController.withFinderCopy()
    }
    
    @objc
    public func finderCornerRadius(_ value: NSNumber?){
        scannerViewController.viewFinderConfiguration.lineCornerRadius = value?.doubleValue ?? defaults.finderCornerRadius
        scannerViewController.withFinderCopy()
    }
    
    @objc
    public func finderMinimumPadding(_ value: NSNumber?){
        if let minValue = value {
            scannerViewController.viewFinderConfiguration.minimumInset = UIEdgeInsets(top: CGFloat(minValue.floatValue),
                                                                                      left: CGFloat(minValue.floatValue),
                                                                                      bottom: CGFloat(minValue.floatValue),
                                                                                      right: CGFloat(minValue.floatValue))
        } else {
            scannerViewController.viewFinderConfiguration.minimumInset = defaults.finderMinimumPadding
        }
        scannerViewController.withFinderCopy()
    }
    
    @objc
    public func finderAspectRatio(_ value: NSDictionary?){
        scannerViewController.viewFinderConfiguration.aspectRatio = SBSDKAspectRatio.fromDictionary(value as? [String : Any]) ?? defaults.finderAspectRatio
        scannerViewController.withFinderCopy()
    }
    
    @objc
    public func polygonEnabled(_ value: Bool){
        scannerViewController.suppressPolygonLayer = !value
    }
    
    @objc
    public func polygonBackgroundColor(_ value: UIColor?) {
        scannerViewController.polygonConfigurationRejected.fillColor = value?.transparentAlpha ?? defaults.polygonBackgroundColor
    }
    
    @objc
    public func polygonBackgroundColorOK(_ value: UIColor?){
        scannerViewController.polygonConfigurationAccepted.fillColor = value?.transparentAlpha ?? defaults.polygonBackgroundColorOK
    }
    
    @objc
    public func polygonColor(_ value: UIColor?){
        scannerViewController.polygonConfigurationRejected.strokeColor = value ?? defaults.polygonColor
    }
    
    @objc
    public func polygonColorOK(_ value: UIColor?){
        scannerViewController.polygonConfigurationAccepted.strokeColor = value ?? defaults.polygonColorOK
    }
    
    @objc
    public func polygonLineWidth(_ value: NSNumber?){
        let width = value?.doubleValue ?? defaults.polygonLineWidth
        scannerViewController.polygonConfigurationAccepted.strokeWidth = width
        scannerViewController.polygonConfigurationRejected.strokeWidth = width
    }
    
    @objc
    public func polygonCornerRadius(_ value: NSNumber?){
        let radius = value?.doubleValue ?? defaults.polygonCornerRadius
        scannerViewController.polygonConfigurationAccepted.cornerRadius = radius
        scannerViewController.polygonConfigurationRejected.cornerRadius = radius
        scannerViewController.autoSnapProgressPolygonConfiguration.cornerRadius = radius
    }
    
    @objc
    public func polygonAutoSnapProgressColor(_ value: UIColor?){
        scannerViewController.autoSnapProgressPolygonConfiguration.strokeColor = value ?? defaults.polygonAutoSnapProgressColor
        scannerViewController.withAutoSnapConfigCopy()
    }
    
    @objc
    public func polygonAutoSnapProgressLineWidth(_ value: NSNumber?){
        scannerViewController.autoSnapProgressPolygonConfiguration.strokeWidth = value?.doubleValue ?? defaults.polygonAutoSnapProgressLineWidth
        scannerViewController.withAutoSnapConfigCopy()
    }
    
    @objc
    public func polygonAutoSnapProgressEnabled(_ value: Bool){
        scannerViewController.autoSnapProgressPolygonConfiguration.enabled = value
        scannerViewController.withAutoSnapConfigCopy()
    }
    
    //MARK: Controls
    
    @objc
    public func freezeCamera() {
        scannerViewController.freezeCamera()
    }
    
    @objc
    public func unfreezeCamera(){
        scannerViewController.unfreezeCamera()
    }
    
    @objc
    public func snapDocument(){
        scannerViewController.captureDocumentImage()
    }
    
    @objc
    public func onDocumentDetectionStatus(result: SBSDKDocumentDetectorResult) -> String? {
        return SBComponentUtils.encodeToString(value: result.status)
    }
    
}
