//
//  DeepARCameraController.swift
//  WoWonder
//
//  Created by iMac on 28/04/25.
//  Copyright © 2025 ScriptSun. All rights reserved.
//

import UIKit
import DeepAR
import AVKit

class DeepARCameraController: UIViewController {
    
    // MARK: - IBOutlets
    
    @IBOutlet weak var arViewContainer: UIView!
    @IBOutlet weak var backButton: UIButton!
    @IBOutlet weak var flashButton: UIButton!
    @IBOutlet weak var maskButton: UIButton!
    @IBOutlet weak var galleryButton: UIButton!
    @IBOutlet weak var cameraButton: CameraButtonView!
    @IBOutlet weak var switchCameraButton: UIButton!
    @IBOutlet weak var cameraControlStack: UIStackView!
    @IBOutlet weak var collectionView: UICollectionView!
    
    // MARK: - Properties
    
    var deepAR = DeepAR()
    private var arView = UIView()
    private var cameraController = CameraController()
    private var isFlashOn = false
    private var isMaskOn = false
    private var faceList: [FaceModel] = []
    private var imagePicker = UIImagePickerController()
    
    // MARK: - View Life Cycles
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        
        self.initialConfig()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        self.deepAR.shutdown()
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        
        self.arView.frame = self.view.bounds
    }
    
    // MARK: - Selectors
    
    // Back Button Action
    @IBAction func backButtonAction(_ sender: UIButton) {
        self.view.endEditing(true)
        self.navigationController?.popViewController(animated: true)
    }
    
    // Mask Button Action
    @IBAction func maskButtonAction(_ sender: UIButton) {
        self.view.endEditing(true)
        self.isMaskOn.toggle()
        self.cameraControlStack.isHidden = self.isMaskOn
        self.collectionView.isHidden = !self.isMaskOn
    }
    
    // Flash Button Action
    @IBAction func flashButtonAction(_ sender: UIButton) {
        self.view.endEditing(true)
        self.isFlashOn.toggle()
        AVCaptureDevice.default(for: .video)
        guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
        do {
            try device.lockForConfiguration()
            device.torchMode = self.isFlashOn ? .on : .off
            device.unlockForConfiguration()
        } catch {
            print("Torch could not be used: \(error)")
        }
    }
    
    // Gallery Button Action
    @IBAction func galleryButtonAction(_ sender: UIButton) {
        self.view.endEditing(true)
        self.imagePicker.delegate = self
        self.imagePicker.sourceType = .photoLibrary
        self.imagePicker.mediaTypes = ["public.movie", "public.image"]
        self.imagePicker.allowsEditing = false
        self.present(self.imagePicker, animated: true, completion: nil)
    }
    
    // Switch Camera Button Action
    @IBAction func switchCameraButtonAction(_ sender: UIButton) {
        self.view.endEditing(true)
        if self.cameraController?.position == .back {
            self.cameraController?.position = .front
        } else {
            self.cameraController?.position = .back
        }
        self.flashButton.isHidden = self.cameraController?.position != .back
        self.isFlashOn = false
    }
    
    // MARK: - Helper Functions
    
    // Initial Config
    func initialConfig() {
        self.initializeDeepAR()
        self.createCameraController()
        self.setupUI()
        self.setupCameraButton()
        self.setupCollectionView()
        self.setFaceFilterData()
    }
    
    // Setup UI
    func setupUI() {
        self.flashButton.isHidden = self.cameraController?.position != .back
        self.cameraControlStack.isHidden = self.isMaskOn
        self.collectionView.isHidden = !self.isMaskOn
    }
    
    // Initialize Deep AR
    func initializeDeepAR() {
        self.deepAR.delegate = self
        self.deepAR.setLicenseKey(ControlSettings.deepArKey)
        self.deepAR.initialize()
    }
    
    // Create Camera Controller
    func createCameraController() {
        self.cameraController = CameraController(deepAR: self.deepAR)
        
        self.arView = self.deepAR.createARView(withFrame: self.arViewContainer.frame)
        self.arView.translatesAutoresizingMaskIntoConstraints = false
        self.arViewContainer.addSubview(self.arView)
        self.arView.leftAnchor.constraint(equalTo: self.arViewContainer.leftAnchor, constant: 0).isActive = true
        self.arView.rightAnchor.constraint(equalTo: self.arViewContainer.rightAnchor, constant: 0).isActive = true
        self.arView.topAnchor.constraint(equalTo: self.arViewContainer.topAnchor, constant: 0).isActive = true
        self.arView.bottomAnchor.constraint(equalTo: self.arViewContainer.bottomAnchor, constant: 0).isActive = true
        
        self.cameraController?.startCamera(withAudio: true)
    }
    
    // Setup Collection View
    func setupCollectionView() {
        self.collectionView.delegate = self
        self.collectionView.dataSource = self
        self.collectionView.register(UINib(resource: R.nib.faceFilterItemCell), forCellWithReuseIdentifier: R.reuseIdentifier.faceFilterItemCell.identifier)
    }
    
    // Set Face Filter Data
    func setFaceFilterData() {
        self.faceList = FaceFiltersUtils.faceFiltersList()
        self.collectionView.reloadData()
    }
    
    // Setup Camera Button
    func setupCameraButton() {
        self.cameraButton.delegate = self
    }
    
}

// MARK: - Extension

// MARK: Collection View Setup
extension DeepARCameraController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.faceList.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let item = self.faceList[indexPath.item]
        let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: R.reuseIdentifier.faceFilterItemCell.identifier, for: indexPath) as! FaceFilterItemCell
        cell.setData(item: item)
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.deepAR.switchEffect(withSlot: "mask", path: nil)
        self.deepAR.switchEffect(withSlot: "face", path: nil)
        self.deepAR.switchEffect(withSlot: "background", path: nil)
        let item = self.faceList[indexPath.item]
        FaceFiltersUtils.getFilterPath(filterName: item.name, filterUrl: item.url) { path in
            self.deepAR.switchEffect(withSlot: item.type, path: path)
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let height = self.collectionView.frame.height
        return CGSizeMake(height, height)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
}

// MARK: CameraButtonDelegate
extension DeepARCameraController: CameraButtonDelegate {
    
    func onStartRecord() {
        let time = "\(Int64(Date().timeIntervalSince1970 * 1000))"
        let fileManager = FileManager.default
        let moviesDerectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("Wowonder_Messenger").appendingPathComponent("Movies")
        if !fileManager.fileExists(atPath: moviesDerectory.path) {
            do {
                try fileManager.createDirectory(at: moviesDerectory, withIntermediateDirectories: true, attributes: nil)
            } catch {
                print("Failed to create directory: \(error.localizedDescription)")
                return
            }
        }
        print("videoPath >>>>> ", moviesDerectory.path)
        self.deepAR.setVideoRecordingOutputName("\(time)")
        self.deepAR.setVideoRecordingOutputPath(moviesDerectory.path)
        
        let width: Int32 = Int32(deepAR.renderingResolution.width)
        let height: Int32 =  Int32(deepAR.renderingResolution.height)
        deepAR.startVideoRecording(withOutputWidth: width, outputHeight: height)
    }
    
    func onEndRecord() {
        deepAR.finishVideoRecording()
    }
    
    func onDurationTooShortError() {
        deepAR.finishVideoRecording()
    }
    
    func onSingleTap() {
        deepAR.takeScreenshot()
    }
    
    func onCancelled() {
        print(#function)
    }
    
}

// MARK: DeepARDelegate Methods
extension DeepARCameraController: DeepARDelegate {
    
    func didFinishPreparingForVideoRecording() {
        print(#function)
    }
    
    func didStartVideoRecording() {
        print(#function)
    }
    
    func didFinishVideoRecording(_ videoFilePath: String!) {
        print(#function)
        print("videoFilePath >>>>> ", videoFilePath)
        let url = URL(fileURLWithPath: videoFilePath)
        if let newVC = R.storyboard.story.videoEditorVC() {
            newVC.isStory = true
            newVC.videoUrl = url
            self.navigationController?.pushViewController(newVC, animated: true)
        }
    }
    
    func recordingFailedWithError(_ error: Error!) {
        print("error >>>>> ", error.localizedDescription)
    }
    
    func didTakeScreenshot(_ screenshot: UIImage!) {
        if let newVC = R.storyboard.story.addNewStoryVC() {
            newVC.selectedImage = screenshot
            self.navigationController?.pushViewController(newVC, animated: true)
        }
    }
    
    func didInitialize() {
        print(#function)
        if (deepAR.videoRecordingWarmupEnabled) {
            DispatchQueue.main.async { [self] in
                let width: Int32 = Int32(deepAR.renderingResolution.width)
                let height: Int32 =  Int32(deepAR.renderingResolution.height)
                deepAR.startVideoRecording(withOutputWidth: width, outputHeight: height)
            }
        }
    }
    
    func didFinishShutdown() {
        print(#function)
    }
    
    func faceVisiblityDidChange(_ faceVisible: Bool) {
        print("faceVisible >>>>> ", faceVisible)
    }
    
}

// MARK: UIImagePickerControllerDelegate & UINavigationControllerDelegate Methods
extension DeepARCameraController: UIImagePickerControllerDelegate & UINavigationControllerDelegate {
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true) {
            if let image = info[.originalImage] as? UIImage {
                if let newVC = R.storyboard.story.addNewStoryVC() {
                    newVC.selectedImage = image
                    self.navigationController?.pushViewController(newVC, animated: true)
                }
            }
            if let videoURL = info[.mediaURL] as? URL {
                if let newVC = R.storyboard.story.videoEditorVC() {
                    newVC.isStory = true
                    newVC.videoUrl = videoURL
                    self.navigationController?.pushViewController(newVC, animated: true)
                }
            }
        }
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
    
}
