//
// [Link]
// CameraSDK
//
// Created by Vlad Cotfas on 17.09.2024.
//
import Foundation
import AVFoundation
import LocalAuthentication
import UIKit
public class CameraSDKImpl: NSObject, CameraSDKProtocol,
UIImagePickerControllerDelegate, UINavigationControllerDelegate {
private weak var delegate: CameraSDKDelegate?
private var isAuthenticated: Bool = false
private let biometricPolicy: LAPolicy
= .deviceOwnerAuthenticationWithBiometrics
public override init() {}
public func setDelegate(_ delegate: CameraSDKDelegate?) {
[Link] = delegate
}
public func takePhoto() {
let cameraAuthorizationStatus =
[Link](for: .video)
switch cameraAuthorizationStatus {
case .denied, .restricted:
// Access denied or restricted, redirect user to settings
print("Camera needs permission, please enable it from settings")
openSettings()
case .notDetermined, .authorized:
// Check if camera is available
if [Link](.camera) {
openCamera()
} else {
// Camera is not available
print("Camera is not available")
delegate?.didOnError("Camera is not available")
}
@unknown default:
// Other errors
print("Other errors on takePhoto")
delegate?.didOnError("Other errors on takePhoto")
}
}
public func accessPhotos() {
[Link](qos: .background).async {
if ![Link] {
[Link](nil)
return
}
let fileManager = [Link]
do {
let photoURLs = try [Link](at:
[Link], includingPropertiesForKeys: nil)
// Sort photoURLs by creation date in descending order
let sortedPhotoURLs = [Link] {
let creationDate1 = (try? [Link](atPath:
$[Link])[.creationDate] as? Date) ?? [Link]
let creationDate2 = (try? [Link](atPath:
$[Link])[.creationDate] as? Date) ?? [Link]
return creationDate1 > creationDate2
}
[Link](sortedPhotoURLs)
} catch {
[Link](nil)
}
}
}
public func authenticateUser() {
let context = LAContext()
var error: NSError?
if [Link](biometricPolicy, error: &error) {
let reason = "Authenticate to access photos"
[Link](biometricPolicy, localizedReason: reason)
{ success, error in
[Link] {
if success {
[Link] = true
[Link]?.didAuthenticate(success: true, error: nil)
} else {
[Link] = false
[Link]?.didAuthenticate(success: false, error:
error)
}
}
}
} else {
[Link]?.didAuthenticate(success: false, error: error)
}
}
private func openCamera() {
[Link] {
if let rootViewController =
[Link]?.rootViewController {
let imagePickerController = UIImagePickerController()
[Link] = self
[Link] = .camera
[Link] = .front
[Link] = ["[Link]"]
[Link](imagePickerController, animated: true,
completion: nil)
}
}
}
// overridden methods
public func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [[Link] : Any]) {
[Link](animated: true) {
if let image = info[.originalImage] as? UIImage {
// Save image to disk
[Link](image)
} else {
[Link]?.didTakePhoto(success: false, photoURL: nil)
}
}
}
// overridden methods
public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
[Link]?.didTakePhoto(success: false, photoURL: nil)
[Link](animated: true, completion: nil)
}
private func saveImage(_ image: UIImage) {
[Link](qos: .background).async {
let timestamp = Date().timeIntervalSince1970
let filename = "selfie_\(timestamp).jpg"
let fileURL = [Link](filename)
guard let imageData = [Link](compressionQuality: 1.0) else {
[Link](success: false, photoURL: nil)
return
}
do {
try [Link](to: fileURL)
[Link](success: true, photoURL: fileURL)
} catch {
[Link](success: false, photoURL: nil)
}
}
}
private var photoDirectory: URL {
let fileManager = [Link]
let urls = [Link](for: .documentDirectory, in: .userDomainMask)
let dir = urls[0].appendingPathComponent("SelfiePhotos")
if  {
try? [Link](at: dir, withIntermediateDirectories:
true, attributes: nil)
}
return dir
}
private func openSettings() {
if let settingsUrl = URL(string: [Link]) {
if [Link](settingsUrl) {
[Link](settingsUrl, options: [:],
completionHandler: nil)
}
}
}
private func notifyDelegateOnMainThread(success: Bool, photoURL: URL?) {
[Link] {
[Link]?.didTakePhoto(success: success, photoURL: photoURL)
}
}
private func notifyDelegateOnMainThreadWithPhotos(_ photoURLs: [URL]?) {
[Link] {
[Link]?.didAccessPhotos(photoURLs)
}
}
}