import Foundation
import SwiftUI
import BioPassID
import AVFoundation

public class Utils {
    public static func dictionaryToFaceConfig(config: NSDictionary) -> FaceConfig {
        let faceConfig = config as! Dictionary<String, Any>
        
        var resolutionPreset: FaceResolutionPreset = .MEDIUM
        let resolutionPresetString = faceConfig["resolutionPreset"] as! String
        if (resolutionPresetString == "LOW") {
            resolutionPreset = .LOW
        } else if (resolutionPresetString == "MEDIUM") {
            resolutionPreset = .MEDIUM
        } else if (resolutionPresetString == "HIGH") {
            resolutionPreset = .HIGH
        } else if (resolutionPresetString == "VERYHIGH") {
            resolutionPreset = .VERYHIGH
        } else if (resolutionPresetString == "ULTRAHIGH") {
            resolutionPreset = .ULTRAHIGH
        } else{
            resolutionPreset = .MAX
        }
        
        let lensDirection: FaceCameraLensDirection
        let lensDirectionString = faceConfig["lensDirection"] as! String
        if (lensDirectionString == "FRONT") {
            lensDirection = .FRONT
        } else {
            lensDirection = .BACK
        }
        
        var imageFormat: FaceImageFormat
        let imageFormatString = faceConfig["imageFormat"] as! String
        if (imageFormatString == "JPEG") {
            imageFormat = .JPEG
        } else {
            imageFormat = .PNG
        }
        
        let licenseKey = faceConfig["licenseKey"] as! String
        let flashEnabled = faceConfig["flashEnabled"] as! Bool
        let fontFamily = faceConfig["fontFamily"] as! String
        
        //MARK: GETS FACE DETECTION OPTIONS PROPERTIES
        let mapFaceLiveness = faceConfig["liveness"] as! Dictionary<String, AnyObject>
        let faceLivenessEnabled = mapFaceLiveness["enabled"] as! Bool
        let faceLivenessDebug = mapFaceLiveness["debug"] as! Bool
        let faceLivenessTimeToCapture = mapFaceLiveness["timeToCapture"] as! Int
        let faceLivenessMaxFaceDetectionTime = mapFaceLiveness["maxFaceDetectionTime"] as! Int
        let faceLivenessMinFaceProp = mapFaceLiveness["minFaceProp"] as! Double
        let faceLivenessMaxFaceProp = mapFaceLiveness["maxFaceProp"] as! Double
        let faceLivenessMinFaceWidth = mapFaceLiveness["minFaceWidth"] as! Int
        let faceLivenessMinFaceHeight = mapFaceLiveness["minFaceHeight"] as! Int
        let faceLivenessIed = mapFaceLiveness["ied"] as! Int
        let faceLivenessBboxPad = mapFaceLiveness["bboxPad"] as! Int
        let faceLivenessFaceDetectionThresh = mapFaceLiveness["faceDetectionThresh"] as! Double
        let faceLivenessRollThresh = mapFaceLiveness["rollThresh"] as! Double
        let faceLivenessPitchThresh = mapFaceLiveness["pitchThresh"] as! Double
        let faceLivenessYawThresh = mapFaceLiveness["yawThresh"] as! Double
        let faceLivenessTooDarkThresh = mapFaceLiveness["tooDarkThresh"] as! Int
        let faceLivenessTooLightThresh = mapFaceLiveness["tooLightThresh"] as! Int
        let faceLivenessFaceCentralizationThresh = mapFaceLiveness["faceCentralizationThresh"] as! Double
        
        //MARK: GETS CONTINUOUS CAPTURE OPTIONS PROPERTIES
        let mapContinuousCapture = faceConfig["continuousCapture"] as! Dictionary<String, AnyObject>
        let continuousCaptureEnabled = mapContinuousCapture["enabled"] as! Bool
        let continuousCaptureTimeToCapture = mapContinuousCapture["timeToCapture"] as! Int
        let continuousCaptureMaxNumberFrames = mapContinuousCapture["maxNumberFrames"] as! Int
        
        //MARK: GETS FACE DETECTION OPTIONS PROPERTIES
        let mapFaceDetection = faceConfig["faceDetection"] as! Dictionary<String, AnyObject>
        let faceDetectionEnabled = mapFaceDetection["enabled"] as! Bool
        let faceDetectionAutoCapture = mapFaceDetection["autoCapture"] as! Bool
        let faceDetectionMultipleFacesEnabled = mapFaceDetection["multipleFacesEnabled"] as! Bool
        let faceDetectionTimeToCapture = mapFaceDetection["timeToCapture"] as! Int
        let faceDetectionMaxFaceDetectionTime = mapFaceDetection["maxFaceDetectionTime"] as! Int
        let faceDetectionScoreThreshold = mapFaceDetection["scoreThreshold"] as! Double
        
        //MARK: GETS MASK OPTIONS PROPERTIES
        let mapMask = faceConfig["mask"] as! Dictionary<String, AnyObject>
        let maskEnabled = mapMask["enabled"] as! Bool
        var maskType: FaceMaskFormat
        let maskTypeString = mapMask["type"] as! String
        if (maskTypeString == "FACE") {
            maskType = .FACE
        } else if (maskTypeString == "SQUARE") {
            maskType = .SQUARE
        } else {
            maskType = .ELLIPSE
        }
        let maskBackgroundColor = mapMask["backgroundColor"] as! String
        let maskFrameColor = mapMask["frameColor"] as! String
        let maskFrameEnabledColor = mapMask["frameEnabledColor"] as! String
        let maskFrameErrorColor = mapMask["frameErrorColor"] as! String
        
        //MARK: GETS TITLE TEXT PROPERTIES
        let mapTitleText = faceConfig["titleText"] as! Dictionary<String, AnyObject>
        let titleTextEnabled = mapTitleText["enabled"] as! Bool
        let titleTextContent = mapTitleText["content"] as! String
        let titleTextColor = mapTitleText["textColor"] as! String
        let titleTextSize = mapTitleText["textSize"] as! Int
        
        //MARK: GETS HELP TEXT PROPERTIES
        let mapHelpText = faceConfig["helpText"] as! Dictionary<String, AnyObject>
        let helpTextEnabled = mapHelpText["enabled"] as! Bool
        let helpTextContent = mapHelpText["content"] as! String
        let helpTextColor = mapHelpText["textColor"] as! String
        let helpTextSize = mapHelpText["textSize"] as! Int
        
        //MARK: GETS LOADING TEXT PROPERTIES
        let mapLoadingText = faceConfig["loadingText"] as! Dictionary<String, AnyObject>
        let loadingTextEnabled = mapLoadingText["enabled"] as! Bool
        let loadingTextContent = mapLoadingText["content"] as! String
        let loadingTextColor = mapLoadingText["textColor"] as! String
        let loadingTextSize = mapLoadingText["textSize"] as! Int
        
        //MARK: GETS FEEDBACK TEXT PROPERTIES
        let mapFeedbackText = faceConfig["feedbackText"] as! Dictionary<String, AnyObject>
        let feedbackTextEnabled = mapFeedbackText["enabled"] as! Bool
        let feedbackTextColor = mapFeedbackText["textColor"] as! String
        let feedbackTextSize = mapFeedbackText["textSize"] as! Int
        let mapFeedbackTextMessages = mapFeedbackText["messages"] as! Dictionary<String, String>
        let feedbackTextNoDetectionMessage = mapFeedbackTextMessages["noDetection"]!
        let feedbackTextMultipleFacesMessage = mapFeedbackTextMessages["multipleFaces"]!
        let feedbackTextFaceCenteredMessage = mapFeedbackTextMessages["faceCentered"]!
        let feedbackTextTooCloseMessage = mapFeedbackTextMessages["tooClose"]!
        let feedbackTextTooFarMessage = mapFeedbackTextMessages["tooFar"]!
        let feedbackTextTooLeftMessage = mapFeedbackTextMessages["tooLeft"]!
        let feedbackTextTooRightMessage = mapFeedbackTextMessages["tooRight"]!
        let feedbackTextTooUpMessage = mapFeedbackTextMessages["tooUp"]!
        let feedbackTextTooDownMessage = mapFeedbackTextMessages["tooDown"]!
        let feedbackTextInvalidIEDMessage = mapFeedbackTextMessages["invalidIED"]!
        let feedbackTextFaceAngleMisalignedMessage = mapFeedbackTextMessages["faceAngleMisaligned"]!
        let feedbackTextTooDarkMessage = mapFeedbackTextMessages["tooDark"]!
        let feedbackTextTooLightMessage = mapFeedbackTextMessages["tooLight"]!
        
        //MARK: GETS BACK BUTTON PROPERTIES
        let mapBackButton = faceConfig["backButton"] as! Dictionary<String, AnyObject>
        let backButtonEnabled = mapBackButton["enabled"] as! Bool
        let backButtonBackgroundColor = mapBackButton["backgroundColor"] as! String
        let backButtonPadding = mapBackButton["buttonPadding"] as! Int
        let mapBackButtonSize = mapBackButton["buttonSize"] as! Dictionary<String, Double>
        let backButtonSize = CGSize(
            width: mapBackButtonSize["width"]!,
            height: mapBackButtonSize["height"]!
        )
        let mapBackButtonIcon = mapBackButton["iconOptions"] as! Dictionary<String, AnyObject>
        let backButtonIconEnabled = mapBackButtonIcon["enabled"] as! Bool
        let backButtonIconFile = mapBackButtonIcon["iconFile"] as! String
        let backButtonIconColor = mapBackButtonIcon["iconColor"] as! String
        let mapBackButtonIconSize = mapBackButtonIcon["iconSize"] as! Dictionary<String, Double>
        let backButtonIconSize = CGSize(
            width: mapBackButtonIconSize["width"]!,
            height: mapBackButtonIconSize["height"]!
        )
        let mapBackButtonLabel = mapBackButton["labelOptions"] as! Dictionary<String, AnyObject>
        let backButtonLabelEnabled = mapBackButtonLabel["enabled"] as! Bool
        let backButtonLabelContent = mapBackButtonLabel["content"] as! String
        let backButtonLabelTextColor = mapBackButtonLabel["textColor"] as! String
        let backButtonLabelTextSize = mapBackButtonLabel["textSize"] as! Int
        
        //MARK: GETS FLASH BUTTON PROPERTIES
        let mapFlashButton = faceConfig["flashButton"] as! Dictionary<String, AnyObject>
        let flashButtonEnabled = mapFlashButton["enabled"] as! Bool
        let flashButtonBackgroundColor = mapFlashButton["backgroundColor"] as! String
        let flashButtonPadding = mapFlashButton["buttonPadding"] as! Int
        let mapFlashButtonSize = mapFlashButton["buttonSize"] as! Dictionary<String, Double>
        let flashButtonSize = CGSize(
            width: mapFlashButtonSize["width"]!,
            height: mapFlashButtonSize["height"]!
        )
        
        //MARK: GETS FLASH ON PROPERTIES
        let mapFlashOnButtonIcon = mapFlashButton["flashOnIconOptions"] as! Dictionary<String, AnyObject>
        let flashOnButtonIconEnabled = mapFlashOnButtonIcon["enabled"] as! Bool
        let flashOnButtonIconFile = mapFlashOnButtonIcon["iconFile"] as! String
        let flashOnButtonIconColor = mapFlashOnButtonIcon["iconColor"] as! String
        let mapFlashOnButtonIconSize = mapFlashOnButtonIcon["iconSize"] as! Dictionary<String, Double>
        let flashOnButtonIconSize = CGSize(
            width: mapFlashOnButtonIconSize["width"]!,
            height: mapFlashOnButtonIconSize["height"]!
        )
        let mapFlashOnButtonLabel = mapFlashButton["flashOnLabelOptions"] as! Dictionary<String, AnyObject>
        let flashOnButtonLabelEnabled = mapFlashOnButtonLabel["enabled"] as! Bool
        let flashOnButtonLabelContent = mapFlashOnButtonLabel["content"] as! String
        let flashOnButtonLabelTextColor = mapFlashOnButtonLabel["textColor"] as! String
        let flashOnButtonLabelTextSize = mapFlashOnButtonLabel["textSize"] as! Int
        
        //MARK: GETS FLASH OFF PROPERTIES
        let mapFlashOffButtonIcon = mapFlashButton["flashOffIconOptions"] as! Dictionary<String, AnyObject>
        let flashOffButtonIconEnabled = mapFlashOffButtonIcon["enabled"] as! Bool
        let flashOffButtonIconFile = mapFlashOffButtonIcon["iconFile"] as! String
        let flashOffButtonIconColor = mapFlashOffButtonIcon["iconColor"] as! String
        let mapFlashOffButtonIconSize = mapFlashOffButtonIcon["iconSize"] as! Dictionary<String, Double>
        let flashOffButtonIconSize = CGSize(
            width: mapFlashOffButtonIconSize["width"]!,
            height: mapFlashOffButtonIconSize["height"]!
        )
        let mapFlashOffButtonLabel = mapFlashButton["flashOffLabelOptions"] as! Dictionary<String, AnyObject>
        let flashOffButtonLabelEnabled = mapFlashOffButtonLabel["enabled"] as! Bool
        let flashOffButtonLabelContent = mapFlashOffButtonLabel["content"] as! String
        let flashOffButtonLabelTextColor = mapFlashOffButtonLabel["textColor"] as! String
        let flashOffButtonLabelTextSize = mapFlashOffButtonLabel["textSize"] as! Int
        
        //MARK: GETS SWITCH CAMERA BUTTON PROPERTIES
        let mapSwitchCameraButton = faceConfig["switchCameraButton"] as! Dictionary<String, AnyObject>
        let switchCameraButtonEnabled = mapSwitchCameraButton["enabled"] as! Bool
        let switchCameraButtonBackgroundColor = mapSwitchCameraButton["backgroundColor"] as! String
        let switchCameraButtonPadding = mapSwitchCameraButton["buttonPadding"] as! Int
        let mapSwitchCameraButtonSize = mapSwitchCameraButton["buttonSize"] as! Dictionary<String, Double>
        let switchCameraButtonSize = CGSize(
            width: mapSwitchCameraButtonSize["width"]!,
            height: mapSwitchCameraButtonSize["height"]!
        )
        let mapSwitchCameraButtonIcon = mapSwitchCameraButton["iconOptions"] as! Dictionary<String, AnyObject>
        let switchCameraButtonIconEnabled = mapSwitchCameraButtonIcon["enabled"] as! Bool
        let switchCameraButtonIconFile = mapSwitchCameraButtonIcon["iconFile"] as! String
        let switchCameraButtonIconColor = mapSwitchCameraButtonIcon["iconColor"] as! String
        let mapSwitchCameraButtonIconSize = mapSwitchCameraButtonIcon["iconSize"] as! Dictionary<String, Double>
        let switchCameraButtonIconSize = CGSize(
            width: mapSwitchCameraButtonIconSize["width"]!,
            height: mapSwitchCameraButtonIconSize["height"]!
        )
        let mapSwitchCameraButtonLabel = mapSwitchCameraButton["labelOptions"] as! Dictionary<String, AnyObject>
        let switchCameraButtonLabelEnabled = mapSwitchCameraButtonLabel["enabled"] as! Bool
        let switchCameraButtonLabelContent = mapSwitchCameraButtonLabel["content"] as! String
        let switchCameraButtonLabelTextColor = mapSwitchCameraButtonLabel["textColor"] as! String
        let switchCameraButtonLabelTextSize = mapSwitchCameraButtonLabel["textSize"] as! Int
        
        //MARK: GETS CAPTURE BUTTON PROPERTIES
        let mapCaptureButton = faceConfig["captureButton"] as! Dictionary<String, AnyObject>
        let captureButtonEnabled = mapCaptureButton["enabled"] as! Bool
        let captureButtonBackgroundColor = mapCaptureButton["backgroundColor"] as! String
        let captureButtonPadding = mapCaptureButton["buttonPadding"] as! Int
        let mapCaptureButtonSize = mapCaptureButton["buttonSize"] as! Dictionary<String, Double>
        let captureButtonSize = CGSize(
            width: mapCaptureButtonSize["width"]!,
            height: mapCaptureButtonSize["height"]!
        )
        let mapCaptureButtonIcon = mapCaptureButton["iconOptions"] as! Dictionary<String, AnyObject>
        let captureButtonIconEnabled = mapCaptureButtonIcon["enabled"] as! Bool
        let captureButtonIconFile = mapCaptureButtonIcon["iconFile"] as! String
        let captureButtonIconColor = mapCaptureButtonIcon["iconColor"] as! String
        let mapCaptureButtonIconSize = mapCaptureButtonIcon["iconSize"] as! Dictionary<String, Double>
        let captureButtonIconSize = CGSize(
            width: mapCaptureButtonIconSize["width"]!,
            height: mapCaptureButtonIconSize["height"]!
        )
        let mapCaptureButtonLabel = mapCaptureButton["labelOptions"] as! Dictionary<String, AnyObject>
        let captureButtonLabelEnabled = mapCaptureButtonLabel["enabled"] as! Bool
        let captureButtonLabelContent = mapCaptureButtonLabel["content"] as! String
        let captureButtonLabelTextColor = mapCaptureButtonLabel["textColor"] as! String
        let captureButtonLabelTextSize = mapCaptureButtonLabel["textSize"] as! Int
        
        let config = FaceConfig()
        config.licenseKey = licenseKey
        config.resolutionPreset = resolutionPreset
        config.lensDirection = lensDirection
        config.imageFormat = imageFormat
        config.flashEnabled = flashEnabled
        config.fontFamily = fontFamily
        
        //MARK: SETS FACE DETECTION OPTIONS PROPERTIES
        config.liveness.enabled = faceLivenessEnabled
        config.liveness.debug = faceLivenessDebug
        config.liveness.timeToCapture = faceLivenessTimeToCapture
        config.liveness.maxFaceDetectionTime = faceLivenessMaxFaceDetectionTime
        config.liveness.minFaceProp = Float(faceLivenessMinFaceProp)
        config.liveness.maxFaceProp = Float(faceLivenessMaxFaceProp)
        config.liveness.minFaceWidth = faceLivenessMinFaceWidth
        config.liveness.minFaceHeight = faceLivenessMinFaceHeight
        config.liveness.ied = faceLivenessIed
        config.liveness.bboxPad = faceLivenessBboxPad
        config.liveness.faceDetectionThresh = Float(faceLivenessFaceDetectionThresh)
        config.liveness.rollThresh = Float(faceLivenessRollThresh)
        config.liveness.pitchThresh = Float(faceLivenessPitchThresh)
        config.liveness.yawThresh = Float(faceLivenessYawThresh)
        config.liveness.tooDarkThresh = faceLivenessTooDarkThresh
        config.liveness.tooLightThresh = faceLivenessTooLightThresh
        config.liveness.faceCentralizationThresh = Float(faceLivenessFaceDetectionThresh)
        
        //MARK: GETS CONTINUOUS CAPTURE OPTIONS PROPERTIES
        config.continuousCapture.enabled = continuousCaptureEnabled
        config.continuousCapture.timeToCapture = continuousCaptureTimeToCapture
        config.continuousCapture.maxNumberFrames = continuousCaptureMaxNumberFrames
        
        //MARK: SETS FACE DETECTION OPTIONS PROPERTIES
        config.faceDetection.enabled = faceDetectionEnabled
        config.faceDetection.autoCapture = faceDetectionAutoCapture
        config.faceDetection.multipleFacesEnabled = faceDetectionMultipleFacesEnabled
        config.faceDetection.timeToCapture = faceDetectionTimeToCapture
        config.faceDetection.maxFaceDetectionTime = faceDetectionMaxFaceDetectionTime
        config.faceDetection.scoreThreshold = Float(CGFloat(faceDetectionScoreThreshold))
        
        //MARK: SETS MASK OPTIONS PROPERTIES
        config.mask.enabled = maskEnabled
        config.mask.type = maskType
        config.mask.backgroundColor = Color.convertHexStringToColor(hexString: maskBackgroundColor) ?? config.mask.backgroundColor
        config.mask.frameColor = Color.convertHexStringToColor(hexString: maskFrameColor) ?? config.mask.frameColor
        config.mask.frameEnabledColor = Color.convertHexStringToColor(hexString: maskFrameEnabledColor) ?? config.mask.frameEnabledColor
        config.mask.frameErrorColor = Color.convertHexStringToColor(hexString: maskFrameErrorColor) ?? config.mask.frameErrorColor
        
        //MARK: SETS TITLE TEXT PROPERTIES
        config.titleText.enabled = titleTextEnabled
        config.titleText.content = titleTextContent
        config.titleText.textColor = Color.convertHexStringToColor(hexString: titleTextColor) ?? config.titleText.textColor
        config.titleText.textSize = CGFloat(titleTextSize)
        
        //MARK: SETS HELP TEXT PROPERTIES
        config.helpText.enabled = helpTextEnabled
        config.helpText.content = helpTextContent
        config.helpText.textColor = Color.convertHexStringToColor(hexString: helpTextColor) ?? config.helpText.textColor
        config.helpText.textSize = CGFloat(helpTextSize)
        
        //MARK: SETS LOADING TEXT PROPERTIES
        config.loadingText.enabled = loadingTextEnabled
        config.loadingText.content = loadingTextContent
        config.loadingText.textColor = Color.convertHexStringToColor(hexString: loadingTextColor) ?? config.loadingText.textColor
        config.loadingText.textSize = CGFloat(loadingTextSize)
        
        //MARK: SETS FEEDBACK TEXT PROPERTIES
        config.feedbackText.enabled = feedbackTextEnabled
        config.feedbackText.textColor = Color.convertHexStringToColor(hexString: feedbackTextColor) ?? config.feedbackText.textColor
        config.feedbackText.textSize = CGFloat(feedbackTextSize)
        config.feedbackText.messages.noDetection = feedbackTextNoDetectionMessage
        config.feedbackText.messages.multipleFaces = feedbackTextMultipleFacesMessage
        config.feedbackText.messages.faceCentered = feedbackTextFaceCenteredMessage
        config.feedbackText.messages.tooClose = feedbackTextTooCloseMessage
        config.feedbackText.messages.tooFar = feedbackTextTooFarMessage
        config.feedbackText.messages.tooLeft = feedbackTextTooLeftMessage
        config.feedbackText.messages.tooRight = feedbackTextTooRightMessage
        config.feedbackText.messages.tooUp = feedbackTextTooUpMessage
        config.feedbackText.messages.tooDown = feedbackTextTooDownMessage
        
        //MARK: SETS BACK BUTTON PROPERTIES
        config.backButton.enabled = backButtonEnabled
        config.backButton.backgroundColor = Color.convertHexStringToColor(hexString: backButtonBackgroundColor) ?? config.backButton.backgroundColor
        config.backButton.buttonPadding = backButtonPadding
        config.backButton.buttonSize = backButtonSize
        config.backButton.iconOptions.enabled = backButtonIconEnabled
        config.backButton.iconOptions.iconFile = backButtonIconFile
        config.backButton.iconOptions.iconColor = Color.convertHexStringToColor(hexString: backButtonIconColor) ??  config.backButton.iconOptions.iconColor
        config.backButton.iconOptions.iconSize = backButtonIconSize
        config.backButton.labelOptions.enabled = backButtonLabelEnabled
        config.backButton.labelOptions.content = backButtonLabelContent
        config.backButton.labelOptions.textColor = Color.convertHexStringToColor(hexString: backButtonLabelTextColor) ?? config.backButton.labelOptions.textColor
        config.backButton.labelOptions.textSize = CGFloat(backButtonLabelTextSize)
        
        //MARK: SETS FLASH BUTTON PROPERTIES
        config.flashButton.enabled = flashButtonEnabled
        config.flashButton.backgroundColor = Color.convertHexStringToColor(hexString: flashButtonBackgroundColor) ?? config.flashButton.backgroundColor
        config.flashButton.buttonPadding = flashButtonPadding
        config.flashButton.buttonSize = flashButtonSize
        
        //MARK: SETS FLASH ON PROPERTIES
        config.flashButton.flashOnIconOptions.enabled = flashOnButtonIconEnabled
        config.flashButton.flashOnIconOptions.iconFile = flashOnButtonIconFile
        config.flashButton.flashOnIconOptions.iconColor = Color.convertHexStringToColor(hexString: flashOnButtonIconColor) ??  config.flashButton.flashOnIconOptions.iconColor
        config.flashButton.flashOnIconOptions.iconSize = flashOnButtonIconSize
        config.flashButton.flashOnLabelOptions.enabled = flashOnButtonLabelEnabled
        config.flashButton.flashOnLabelOptions.content = flashOnButtonLabelContent
        config.flashButton.flashOnLabelOptions.textColor = Color.convertHexStringToColor(hexString: flashOnButtonLabelTextColor) ?? config.flashButton.flashOnLabelOptions.textColor
        config.flashButton.flashOnLabelOptions.textSize = CGFloat(flashOnButtonLabelTextSize)
        
        //MARK: SETS FLASH OFF PROPERTIES
        config.flashButton.flashOffIconOptions.enabled = flashOffButtonIconEnabled
        config.flashButton.flashOffIconOptions.iconFile = flashOffButtonIconFile
        config.flashButton.flashOffIconOptions.iconColor = Color.convertHexStringToColor(hexString: flashOffButtonIconColor) ??  config.flashButton.flashOffIconOptions.iconColor
        config.flashButton.flashOffIconOptions.iconSize = flashOffButtonIconSize
        config.flashButton.flashOffLabelOptions.enabled = flashOffButtonLabelEnabled
        config.flashButton.flashOffLabelOptions.content = flashOffButtonLabelContent
        config.flashButton.flashOffLabelOptions.textColor = Color.convertHexStringToColor(hexString: flashOffButtonLabelTextColor) ?? config.flashButton.flashOffLabelOptions.textColor
        config.flashButton.flashOffLabelOptions.textSize = CGFloat(flashOffButtonLabelTextSize)
        
        //MARK: SETS SWITCH CAMERA BUTTON PROPERTIES
        config.switchCameraButton.enabled = switchCameraButtonEnabled
        config.switchCameraButton.backgroundColor = Color.convertHexStringToColor(hexString: switchCameraButtonBackgroundColor) ?? config.switchCameraButton.backgroundColor
        config.switchCameraButton.buttonPadding = switchCameraButtonPadding
        config.switchCameraButton.buttonSize = switchCameraButtonSize
        config.switchCameraButton.iconOptions.enabled = switchCameraButtonIconEnabled
        config.switchCameraButton.iconOptions.iconFile = switchCameraButtonIconFile
        config.switchCameraButton.iconOptions.iconColor = Color.convertHexStringToColor(hexString: switchCameraButtonIconColor) ??  config.switchCameraButton.iconOptions.iconColor
        config.switchCameraButton.iconOptions.iconSize = switchCameraButtonIconSize
        config.switchCameraButton.labelOptions.enabled = switchCameraButtonLabelEnabled
        config.switchCameraButton.labelOptions.content = switchCameraButtonLabelContent
        config.switchCameraButton.labelOptions.textColor = Color.convertHexStringToColor(hexString: switchCameraButtonLabelTextColor) ?? config.switchCameraButton.labelOptions.textColor
        config.switchCameraButton.labelOptions.textSize = CGFloat(switchCameraButtonLabelTextSize)
        
        //MARK: SETS CAPTURE BUTTON PROPERTIES
        config.captureButton.enabled = captureButtonEnabled
        config.captureButton.backgroundColor = Color.convertHexStringToColor(hexString: captureButtonBackgroundColor) ?? config.captureButton.backgroundColor
        config.captureButton.buttonPadding = captureButtonPadding
        config.captureButton.buttonSize = captureButtonSize
        config.captureButton.iconOptions.enabled = captureButtonIconEnabled
        config.captureButton.iconOptions.iconFile = captureButtonIconFile
        config.captureButton.iconOptions.iconColor = Color.convertHexStringToColor(hexString: captureButtonIconColor) ??  config.captureButton.iconOptions.iconColor
        config.captureButton.iconOptions.iconSize = captureButtonIconSize
        config.captureButton.labelOptions.enabled = captureButtonLabelEnabled
        config.captureButton.labelOptions.content = captureButtonLabelContent
        config.captureButton.labelOptions.textColor = Color.convertHexStringToColor(hexString: captureButtonLabelTextColor) ?? config.captureButton.labelOptions.textColor
        config.captureButton.labelOptions.textSize = CGFloat(captureButtonLabelTextSize)
        
        return config
    }
    
    public static func uiImageToBase64(image: UIImage, imageFormat: FaceImageFormat) -> String? {
        let image: UIImage = image
        let imageFlip = flipImageHorizontally(image)
        
        let imageData: Data?
        if (imageFormat == .PNG) {
            imageData = imageFlip.pngData()
        } else {
            imageData = image.jpegData(compressionQuality: 1.0)
        }
        if (imageData != nil) {
            return imageData!.base64EncodedString(options: [])
        }
        return nil
    }
    
    public static func livenessAttributesToDictionary(attributes: FaceAttributes) -> Dictionary<String, Any> {
        let attributesDictionary: Dictionary<String, Any> = [
            "faceProp" : attributes.faceProp,
            "faceWidth" : attributes.faceWidth,
            "faceHeight": attributes.faceHeight,
            "ied" : attributes.ied,
            "bbox" : [
                "left": attributes.bbox.origin.x,
                "top": attributes.bbox.origin.y,
                "right": attributes.bbox.origin.x + attributes.bbox.size.width,
                "bottom": attributes.bbox.origin.y + attributes.bbox.size.height,
            ],
            "rollAngle": attributes.rollAngle,
            "pitchAngle": attributes.pitchAngle,
            "yawAngle": attributes.yawAngle,
            "averageLightIntensity": attributes.averageLightIntensity
        ]
        
        return attributesDictionary
    }
    
    public static func flipImageHorizontally(_ image: UIImage) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
        let context = UIGraphicsGetCurrentContext()!
        context.translateBy(x: image.size.width, y: 0)
        context.scaleBy(x: -1.0, y: 1.0)
        image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
        let flippedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return flippedImage ?? image
    }
}

extension Color {
    static func convertHexStringToColor(hexString: String) -> Color? {
        var cString: String = hexString.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
        
        if (cString.hasPrefix("#")) {
            cString.remove(at: cString.startIndex)
        }
        
        if ((cString.count) != 8 && (cString.count) != 6) {
            return nil
        }
        
        var rgbValue: UInt64 = 0
        Scanner(string: cString).scanHexInt64(&rgbValue)
        
        if ((cString.count) == 8) {
            return Color(.sRGB, red: Double((rgbValue & 0x00FF0000) >> 16) / 255.0, green: Double((rgbValue & 0x0000FF00) >> 8) / 255.0, blue: Double(rgbValue & 0x000000FF) / 255.0, opacity: Double(Int(rgbValue & 0xFF000000) >> 24) / 255.0)
        } else {
            return Color(.sRGB, red: Double((rgbValue & 0xFF0000) >> 16) / 255.0, green: Double((rgbValue & 0x00FF00) >> 8) / 255.0, blue: Double(rgbValue & 0x0000FF) / 255.0)
        }
    }
    
    static func convertHexStringToUIColor(hexString: String) -> UIColor? {
        var formattedString = hexString.trimmingCharacters(in: .whitespacesAndNewlines)
        formattedString = formattedString.replacingOccurrences(of: "#", with: "")
        
        let hexCount = formattedString.count
        if hexCount != 6 && hexCount != 8 {
            return nil
        }
        
        var rgbValue: UInt64 = 0
        Scanner(string: formattedString).scanHexInt64(&rgbValue)
        
        let red = CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0
        let green = CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0
        let blue = CGFloat(rgbValue & 0x0000FF) / 255.0
        
        return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
    }
}
