////
////  AVPlayerVM.swift
////  WOKA
////
////  Created by Bilal on 05/07/2024.
////
//
//import UIKit
//import AVKit
//
//class AVPlayerVM{
//    
//    weak var vc : AVPlayerVC!
//    
//    var player : AVPlayer? = nil
//    var isThumbSeek : Bool = false
//    var timer : Timer?
//    var isFinished = false{
//        didSet{
//            if isFinished{
//                timer?.invalidate()
//                timer = nil
//                vc.reloadBtn.isHidden = false
//                vc.stackCtrView.isHidden = true
//                vc.tintView.isHidden = false
//                vc.sliderStack.isHidden = true
//            }else{
//                vc.reloadBtn.isHidden = true
//                vc.stackCtrView.isHidden = false
//                vc.sliderStack.isHidden = false
//            }
//        }
//    }
//    
//    private var playerLayer : AVPlayerLayer? = nil
//    private var timeObserver : Any? = nil
//
//    func initView(){
//        vc.seekSlider.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
//
//        self.vc.videoTitle.text = vc.titleVideo
//        setupKaraoke()
//
//    }
//
//    @objc func videoDidFinish() {
//        self.isFinished = true
//        
//    }
//    
//    func setupKaraoke(){
//        guard let url = vc.videoURL else{return}
//        hideShowKaraoke(isLoading: true)
//        let avURL = URL(string: url)!
//        let asset = AVAsset(url: avURL)
//        
//        let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(vc.titleVideo?.trimmingCharacters(in: .whitespaces) ?? "extractedAudio").m4a")
//        FileManager.default.clearTmpDirectory()
//        asset.writeAudioTrackToURL(outputURL) { [weak self] isDone, error,url in
//            guard let self else{return}
//            print(isDone, error , url)
//            if error == nil{
//                hideShowKaraoke(isLoading: false)
//            }
//        }
//    }
//    
//    func hideShowKaraoke(isLoading : Bool){
//        DispatchQueue.main.async { [weak self] in
//            guard let self else{return}
//            if isLoading{
//                vc.karaokeLoading.startAnimating()
//                vc.karaokeStack.isHidden = false
//                vc.playPauseRecordStack.isHidden = true
//            }else{
//                vc.karaokeLoading.stopAnimating()
//                vc.karaokeLoading.hidesWhenStopped = true
//                vc.karaokeStack.isHidden = true
//                vc.playPauseRecordStack.isHidden = false
//            }
//        }
//    }
//
//    // MARK: - Setup Video Player
//
//    func setVideoPlayer() {
//        guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
//        
//        if self.player == nil {
//
//            // Create a subview for the video player
//            let playerView = UIView(frame: vc.viewControll.bounds)
//            playerView.backgroundColor = .clear // Make sure the background is clear
//            vc.viewControll.addSubview(playerView)
//            vc.viewControll.sendSubviewToBack(playerView) // Ensure the player view is below other UI elements
//            
//            // Initialize the player
//            let playerItem = AVPlayerItem(url: url)
//            player = AVPlayer(playerItem: playerItem)
//
//            // Add observer for AVPlayerItemFailedToPlayToEndTimeNotification
//            NotificationCenter.default.addObserver(self,
//                                                   selector: #selector(playerItemFailedToPlayToEndTime(_:)),
//                                                   name: .AVPlayerItemFailedToPlayToEndTime,
//                                                   object: playerItem)
//
//            // Add observer for AVPlayerItem's status
//            playerItem.addObserver(self.vc,
//                                   forKeyPath: "status",
//                                   options: [.new, .initial],
//                                   context: nil)
//
//            // Set up the player layer
//            playerLayer = AVPlayerLayer(player: player)
//            playerLayer?.videoGravity = .resizeAspectFill
//            playerLayer?.frame = playerView.bounds
//            
//            if let playerLayer = playerLayer {
//                playerView.layer.addSublayer(playerLayer)
//            }
//            
//            // Add observer for play/pause
//            player?.addObserver(self.vc, forKeyPath: "rate", options: [.new, .initial], context: nil)
//            
//            // Add observer for buffering
//            playerItem.addObserver(self.vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
//            playerItem.addObserver(self.vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
//            
//            // Add observer for video finished playing
//            NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
//            self.setObserverToPlayer()
//            startTimer()
//            player?.play()
//        }
//    }
//    
//    func reloadVideo() {
//        guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
//        
//        // Remove existing observers
//        NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
//        player?.currentItem?.removeObserver(vc, forKeyPath: "status")
//        player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackBufferEmpty")
//        player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp")
//        
//        // Create a new player item
//        let playerItem = AVPlayerItem(url: url)
//        player?.replaceCurrentItem(with: playerItem)
//        
//        // Add observers again
//        NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
//        playerItem.addObserver(vc, forKeyPath: "status", options: [.new, .initial], context: nil)
//        playerItem.addObserver(vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
//        playerItem.addObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
//        
//        player?.play()
//    }
//    
//    func setObserverToPlayer() {
//        let interval = CMTime(seconds: 0.3, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
//        timeObserver = player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { elapsed in
//            self.updatePlayerTime()
//        })
//    }
//    
//    
//    // Handle notification
//    @objc func playerItemFailedToPlayToEndTime(_ notification: Notification) {
//        if let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error {
//            print("Error: \(error.localizedDescription)")
//            handlePlayerError(error)
//        }
//    }
//    
//    func handlePlayerError(_ error: Error) {
//        // Update the UI or show an alert to the user
//        Utilities.alertWithBtnCompletion(title: "Error", msgBody: error.localizedDescription, okBtnStr: "Retry?", vc: vc.self) { [weak self] isDone in
//            guard let self else{return}
//            player?.play()
//        }
//    }
//   
//    // MARK: - ShowHideControls
//    func startTimer(){
//        timer = Timer.scheduledTimer(withTimeInterval: 4.5, repeats: false) { _ in
//            self.showHideControls()
//        }
//    }
//    
//    func showHideControls(){
//        if isFinished{
//            vc.stackCtrView.isHidden = true
//            vc.reloadBtn.isHidden.toggle()
//            vc.sliderStack.isHidden = true
//        }else{
//            vc.reloadBtn.isHidden = true
//            vc.stackCtrView.isHidden.toggle()
//            vc.sliderStack.isHidden.toggle()
//        }
//        
//        vc.tintView.isHidden.toggle()
//        
//        if !vc.stackCtrView.isHidden{
//            startTimer()
//        }
//    }
//
//    // MARK: - Update the player time Label with Slider
//    
//    private func updatePlayerTime() {
//        guard let currentTime = self.player?.currentTime() else { return }
//        guard let duration = self.player?.currentItem?.duration else { return }
//        
//        let currentTimeInSecond = CMTimeGetSeconds(currentTime)
//        let durationTimeInSecond = CMTimeGetSeconds(duration)
//        
//        if self.isThumbSeek == false {
//            self.vc.seekSlider.value = Float(currentTimeInSecond/durationTimeInSecond)
//        }
//        
//        let value = Float64(self.vc.seekSlider.value) * CMTimeGetSeconds(duration)
//        
//        var hours = value / 3600
//        var mins =  (value / 60).truncatingRemainder(dividingBy: 60)
//        var secs = value.truncatingRemainder(dividingBy: 60)
//        var timeformatter = NumberFormatter()
//        timeformatter.minimumIntegerDigits = 2
//        timeformatter.minimumFractionDigits = 0
//        timeformatter.roundingMode = .down
//        guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
//            return
//        }
//        self.vc.lbCurrentTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
//        
//        hours = durationTimeInSecond / 3600
//        mins = (durationTimeInSecond / 60).truncatingRemainder(dividingBy: 60)
//        secs = durationTimeInSecond.truncatingRemainder(dividingBy: 60)
//        timeformatter = NumberFormatter()
//        timeformatter.minimumIntegerDigits = 2
//        timeformatter.minimumFractionDigits = 0
//        timeformatter.roundingMode = .down
//        guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
//            return
//        }
//        self.vc.lbTotalTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
//    }
//}
