import Foundation
import Signature
import AVFoundation
import SwiftUI

public class Utils {
  public static func dictionaryToSignatureConfig(config: NSDictionary) -> SignatureConfig {
    //MARK: SET SIGNATURE CONFIG
    let signatureConfig = config as! Dictionary<String, Any>

    let licenseKey: String = signatureConfig["licenseKey"] as! String
    var screenOrientation: SignatureScreenOrientation = .PORTRAIT
    let setScreenOrientation = signatureConfig["screenOrientation"] as! String
    if (setScreenOrientation == "LANDSCAPE") {
      screenOrientation = .LANDSCAPE
    } else {
      screenOrientation = .PORTRAIT
    }
    
    let pencilColor = signatureConfig["pencilColor"] as! String
    let pencilWidth = signatureConfig["pencilWidth"] as! Int
    let backgroundColor = signatureConfig["backgroundColor"] as! String
    let overlayColor = signatureConfig["overlayColor"] as! String
    let fontFamily = signatureConfig["fontFamily"] as! String

    //MARK: GETS TITLE TEXT PROPRETIES
    let mapTitleText = signatureConfig["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 BACK BUTTON PROPETIES
    let mapBackButton = signatureConfig["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 SAVE BUTTON PROPETIES
    let mapSaveButton = signatureConfig["saveButton"] as! Dictionary<String, AnyObject>
    let saveButtonEnabled = mapSaveButton["enabled"] as! Bool
    let saveButtonBackgroundColor = mapSaveButton["backgroundColor"] as! String
    let saveButtonPadding = mapSaveButton["buttonPadding"] as! Int
    let mapSaveButtonSize = mapSaveButton["buttonSize"]! as! Dictionary<String, Double>
    let saveButtonSize = CGSize(
      width: mapSaveButtonSize["width"]!,
      height: mapSaveButtonSize["height"]!
    )

    let mapSaveButtonIcon = mapSaveButton["iconOptions"] as! Dictionary<String, AnyObject>
    let saveButtonIconEnabled = mapSaveButtonIcon["enabled"] as! Bool
    let saveButtonIconFile = mapSaveButtonIcon["iconFile"] as! String
    let saveButtonIconColor = mapSaveButtonIcon["iconColor"] as! String
    let mapSaveButtonIconSize = mapSaveButtonIcon["iconSize"]! as! Dictionary<String, Double>
    let saveButtonIconSize = CGSize(
      width: mapSaveButtonIconSize["width"]!,
      height: mapSaveButtonIconSize["height"]!
    )

    let mapSaveButtonLabel = mapSaveButton["labelOptions"] as! Dictionary<String, AnyObject>
    let saveButtonLabelEnabled = mapSaveButtonLabel["enabled"] as! Bool
    let saveButtonLabelContent = mapSaveButtonLabel["content"] as! String
    let saveButtonLabelTextColor = mapSaveButtonLabel["textColor"] as! String
    let saveButtonLabelTextSize = mapSaveButtonLabel["textSize"] as! Int

    //MARK: GETS DELETE BUTTON PROPETIES
    let mapDeleteButton = signatureConfig["deleteButton"] as! Dictionary<String, AnyObject>
    let deleteButtonEnabled = mapDeleteButton["enabled"] as! Bool
    let deleteButtonBackgroundColor = mapDeleteButton["backgroundColor"] as! String
    let deleteButtonPadding = mapDeleteButton["buttonPadding"] as! Int
    let mapDeleteButtonSize = mapDeleteButton["buttonSize"]! as! Dictionary<String, Double>
    let deleteButtonSize = CGSize(
      width: mapDeleteButtonSize["width"]!,
      height: mapDeleteButtonSize["height"]!
    )

    let mapDeleteButtonIcon = mapDeleteButton["iconOptions"] as! Dictionary<String, AnyObject>
    let deleteButtonIconEnabled = mapDeleteButtonIcon["enabled"] as! Bool
    let deleteButtonIconFile = mapDeleteButtonIcon["iconFile"] as! String
    let deleteButtonIconColor = mapDeleteButtonIcon["iconColor"] as! String
    let mapDeleteButtonIconSize = mapDeleteButtonIcon["iconSize"]! as! Dictionary<String, Double>
    let deleteButtonIconSize = CGSize(
      width: mapDeleteButtonIconSize["width"]!,
      height: mapDeleteButtonIconSize["height"]!
    )

    let mapDeleteButtonLabel = mapDeleteButton["labelOptions"] as! Dictionary<String, AnyObject>
    let deleteButtonLabelEnabled = mapDeleteButtonLabel["enabled"] as! Bool
    let deleteButtonLabelContent = mapDeleteButtonLabel["content"] as! String
    let deleteButtonLabelTextColor = mapDeleteButtonLabel["textColor"] as! String
    let deleteButtonLabelTextSize = mapDeleteButtonLabel["textSize"] as! Int
    
    //MARK: GETS UNDO BUTTON PROPETIES
    let mapUndoButton = signatureConfig["undoButton"] as! Dictionary<String, AnyObject>
    let undoButtonEnabled = mapUndoButton["enabled"] as! Bool
    let undoButtonBackgroundColor = mapUndoButton["backgroundColor"] as! String
    let undoButtonPadding = mapUndoButton["buttonPadding"] as! Int
    let mapUndoButtonSize = mapUndoButton["buttonSize"]! as! Dictionary<String, Double>
    let undoButtonSize = CGSize(
      width: mapUndoButtonSize["width"]!,
      height: mapUndoButtonSize["height"]!
    )

    let mapUndoButtonIcon = mapUndoButton["iconOptions"] as! Dictionary<String, AnyObject>
    let undoButtonIconEnabled = mapUndoButtonIcon["enabled"] as! Bool
    let undoButtonIconFile = mapUndoButtonIcon["iconFile"] as! String
    let undoButtonIconColor = mapUndoButtonIcon["iconColor"] as! String
    let mapUndoButtonIconSize = mapUndoButtonIcon["iconSize"]! as! Dictionary<String, Double>
    let undoButtonIconSize = CGSize(
      width: mapUndoButtonIconSize["width"]!,
      height: mapUndoButtonIconSize["height"]!
    )

    let mapUndoButtonLabel = mapUndoButton["labelOptions"] as! Dictionary<String, AnyObject>
    let undoButtonLabelEnabled = mapUndoButtonLabel["enabled"] as! Bool
    let undoButtonLabelContent = mapUndoButtonLabel["content"] as! String
    let undoButtonLabelTextColor = mapUndoButtonLabel["textColor"] as! String
    let undoButtonLabelTextSize = mapUndoButtonLabel["textSize"] as! Int

    var config = SignatureConfig()
    config.licenseKey = licenseKey
    config.screenOrientation = screenOrientation
    config.pencilColor = Color.convertHexStringToUIColor(hexString: pencilColor) ?? config.pencilColor
    config.pencilWidth = pencilWidth
    config.backgroundColor = Color.convertHexStringToUIColor(hexString: backgroundColor) ?? config.backgroundColor
    config.overlayColor = Color.convertHexStringToColor(hexString: overlayColor) ?? config.overlayColor
    config.fontFamily = fontFamily

    // 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)

    // 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)

    // Sets save button properties
    config.saveButton.enabled = saveButtonEnabled
    config.saveButton.backgroundColor = Color.convertHexStringToColor(hexString: saveButtonBackgroundColor) ?? config.saveButton.backgroundColor
    config.saveButton.buttonPadding = saveButtonPadding
    config.saveButton.buttonSize = saveButtonSize
    config.saveButton.iconOptions.enabled = saveButtonIconEnabled
    config.saveButton.iconOptions.iconFile = saveButtonIconFile
    config.saveButton.iconOptions.iconColor = Color.convertHexStringToColor(hexString: saveButtonIconColor) ?? config.saveButton.iconOptions.iconColor
    config.saveButton.iconOptions.iconSize = saveButtonIconSize
    config.saveButton.labelOptions.enabled = saveButtonLabelEnabled
    config.saveButton.labelOptions.content = saveButtonLabelContent
    config.saveButton.labelOptions.textColor = Color.convertHexStringToColor(hexString: saveButtonLabelTextColor) ?? config.saveButton.labelOptions.textColor
    config.saveButton.labelOptions.textSize = CGFloat(saveButtonLabelTextSize)

    // Sets delete button properties
    config.deleteButton.enabled = deleteButtonEnabled
    config.deleteButton.backgroundColor = Color.convertHexStringToColor(hexString: deleteButtonBackgroundColor) ?? config.deleteButton.backgroundColor
    config.deleteButton.buttonPadding = deleteButtonPadding
    config.deleteButton.buttonSize = deleteButtonSize
    config.deleteButton.iconOptions.enabled = deleteButtonIconEnabled
    config.deleteButton.iconOptions.iconFile = deleteButtonIconFile
    config.deleteButton.iconOptions.iconColor = Color.convertHexStringToColor(hexString: deleteButtonIconColor) ?? config.deleteButton.iconOptions.iconColor
    config.deleteButton.iconOptions.iconSize = deleteButtonIconSize
    config.deleteButton.labelOptions.enabled = deleteButtonLabelEnabled
    config.deleteButton.labelOptions.content = deleteButtonLabelContent
    config.deleteButton.labelOptions.textColor = Color.convertHexStringToColor(hexString: deleteButtonLabelTextColor) ?? config.deleteButton.labelOptions.textColor
    config.deleteButton.labelOptions.textSize = CGFloat(deleteButtonLabelTextSize)

    // Sets undo button properties
    config.undoButton.enabled = undoButtonEnabled
    config.undoButton.backgroundColor = Color.convertHexStringToColor(hexString: undoButtonBackgroundColor) ?? config.undoButton.backgroundColor
    config.undoButton.buttonPadding = undoButtonPadding
    config.undoButton.buttonSize = undoButtonSize
    config.undoButton.iconOptions.enabled = undoButtonIconEnabled
    config.undoButton.iconOptions.iconFile = undoButtonIconFile
    config.undoButton.iconOptions.iconColor = Color.convertHexStringToColor(hexString: undoButtonIconColor) ?? config.undoButton.iconOptions.iconColor
    config.undoButton.iconOptions.iconSize = undoButtonIconSize
    config.undoButton.labelOptions.enabled = undoButtonLabelEnabled
    config.undoButton.labelOptions.content = undoButtonLabelContent
    config.undoButton.labelOptions.textColor = Color.convertHexStringToColor(hexString: undoButtonLabelTextColor) ?? config.undoButton.labelOptions.textColor
    config.undoButton.labelOptions.textSize = CGFloat(undoButtonLabelTextSize)

    return config
  }
  
  public static func signatureEventToDictionary(image: UIImage) -> String? {
    if let imageData = image.pngData() {
      return imageData.base64EncodedString(options: [])
    }
    return nil
  }
    
}

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)
  }
}


