//
//  JWKaraokePlayerVC.swift
//  WOKA
//
//  Created by MacBook Pro on 09/07/24.
//

import UIKit
import JWPlayerKit
import AVFAudio
import AVFoundation
import GoogleMobileAds

class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
    
    @IBOutlet weak var backButton: UIButton!
    @IBOutlet weak var startRecordBtn: LocalisedElementsButton!
    @IBOutlet weak var playBtn: LocalisedElementsButton!
    @IBOutlet weak var downloadRecordingBtn: LocalisedElementsButton!
    @IBOutlet weak var karaokeStack: UIStackView!
    @IBOutlet weak var karaokeLoading: UIActivityIndicatorView!
    @IBOutlet weak var startStopRecordingStack: UIStackView!
    @IBOutlet weak var outerStack : UIStackView!
    @IBOutlet weak var retryKaraokeBtn: LocalisedElementsButton!
    
    @IBOutlet weak var adView: UIView!
    
    var config: JWPlayerConfiguration!
    var dismissTapped: (() -> Void)?
    
    var isRecording = false
    var isPlaying = false
    
    var audioPlayer = AVPlayer()
    
    var videoID = Int()
    
    var vm = JWKaraokePlayerVM()
    
    deinit{
        NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil)
        NotificationCenter.default.removeObserver(self,name: UIApplication.willEnterForegroundNotification, object: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        vm.vc = self
        vm.initView()
        
        player.configurePlayer(with: config)
        self.delegate = self
        //Disable Picture in Picture
        playerView.allowsPictureInPicturePlayback = false
        playerView.captionStyle = .none
        self.view.bringSubviewToFront(outerStack)
        self.view.bringSubviewToFront(backButton)    
        self.view.bringSubviewToFront(adView)    
        
        // Add observers
        NotificationCenter.default.addObserver(self,selector: #selector(appDidEnterBackground),name: UIApplication.didEnterBackgroundNotification,object: nil)
        NotificationCenter.default.addObserver(self,selector: #selector(appWillEnterForeground),name: UIApplication.willEnterForegroundNotification,object: nil)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        //        self.navigationController?.isNavigationBarHidden = true
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        player.stop()
    }
    
    @IBAction func startRecordingBtnTapped(_ sender: LocalisedElementsButton) {
        if let postID = vm.postID{
            PersistentStorage.shared.addKaraokeCount(postID: postID)
        }

//        if AuthFunc.shareInstance.guestUserLoginPopUp() { return}

        self.playBtn.isEnabled = false
        if isRecording {
            vm.stopRecording()
            
            //make sure the interfacebehaviour is enabbled && updated the record btn title and image
            self.interfaceBehavior = .normal
            sender.setTitle("Start Recording", for: .normal)
        } else {
            //when recording is started change btn name to play and disable it
            playBtn.setTitle("Play", for: .normal)
            playBtn.setImage(UIImage(named: "PlayButtonSmall"), for: .normal)
            playBtn.isEnabled = false
            downloadRecordingBtn.isEnabled = false
            self.player.play()
            
            //make sure the interfacebehaviour is disabled && updated the record btn title and image
            self.interfaceBehavior = .hidden
            vm.startRecording()
            sender.setTitle("Stop Recording", for: .normal)
        }
        isRecording.toggle()
    }
    
    @IBAction func playBtnTapped(_ sender: LocalisedElementsButton) {
        if let postID = vm.postID{
            PersistentStorage.shared.addKaraokeCount(postID: postID)
        }
        if !isPlaying {
            vm.playMixedAudio()
            sender.setTitle("Pause", for: .normal)
            sender.setImage(UIImage(named: "KaraokePause"), for: .normal)
            
            // Disable Recording while playing, hide controls for jwplayer
            self.interfaceBehavior = .hidden

            self.startRecordBtn.isEnabled = false
            self.downloadRecordingBtn.isEnabled = false
        } else {
            sender.setTitle("Play", for: .normal)
            sender.setImage(UIImage(named: "PlayButtonSmall"), for: .normal)
            
            // Disable Recording while playing, hide controls for jwplayer
            self.interfaceBehavior = .normal
            self.startRecordBtn.isEnabled = true
            self.downloadRecordingBtn.isEnabled = true
        }
        
        isPlaying.toggle()
        
        self.player.pause()
        print("Play")
    }
    
    @IBAction func downloadRecording(_ sender: LocalisedElementsButton) {
        if let postID = vm.postID{
            PersistentStorage.shared.addKaraokeCount(postID: postID)
        }
        print("DownloadRecording")
        vm.saveToFilesApp()
    }
    
    @IBAction func backBtnTapped(_ sender: UIButton) {
        if let postID = vm.postID{
            PersistentStorage.shared.addKaraokeCount(postID: postID)
        }
        self.player.stop()
        if let postID = vm.postID{
            Utilities.startProgressHUD(msg: "Syncing...")
            let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
            AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.karaokeVideo.rawValue, duration: duration, catID: 0) { isDone in
                if isDone{
                    K.GVar.reloadContinueKaraoke = true
                    Utilities.dismissProgressHUD()
                    self.dismiss(animated: true)
                }else{
                    Utilities.dismissProgressHUD()
                    self.dismiss(animated: true)
                }
            }
        }
    }
    
    @IBAction func retryBtnTapped(_ sender: LocalisedElementsButton) {
        if let postID = vm.postID{
            PersistentStorage.shared.addKaraokeCount(postID: postID)
        }
        retryKaraokeBtn.isHidden = true
        vm.setupKaraoke()
    }
    
    // MARK: - App LifeCycle HAndler

    @objc func appDidEnterBackground() {
        //when app goes in background make a count
        vm.updateKaraokeVideoView()
        self.player.pause()
        
        self.playBtn.isEnabled = false
        
        if isRecording {
            vm.stopRecording()
            //make sure the interfacebehaviour is enabbled && updated the record btn title and image
            self.interfaceBehavior = .normal
            startRecordBtn.setTitle("Start Recording", for: .normal)
            isRecording = false
        }
    }
    
    @objc func appWillEnterForeground() {
        //reset the start time
        vm.startTimeStamp = Date()
        self.player.play()
    }
    
    // MARK: - JWPlayerViewControllerDelegate

    override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) {
        super.jwplayer(player, didFinishLoadingWithTime: loadTime)
        print("LoadTime", loadTime)
        DispatchQueue.main.async { [weak self] in
            guard let self else{return}
            vm.setupKaraoke()
//            self.startRecordBtn.isEnabled = true
        }
    }
    
    override func jwplayerIsReady(_ player: JWPlayer) {
        super.jwplayerIsReady(player)
        player.seek(to: 0)
        print("IsReady")
    }
    
    override func jwplayer(_ player: JWPlayer, failedWithSetupError code: UInt, message: String) {
        super.jwplayer(player, failedWithSetupError: code, message: message)
        print("Setup Error: \(code) - \(message)")
    }
    
    override func jwplayer(_ player: JWPlayer, failedWithError code: UInt, message: String) {
        super.jwplayer(player, failedWithError: code, message: message)
        // if no internet then add network observer
        print("Error: \(code) - \(message)")
    }
    
    override func jwplayer(_ player: JWPlayer, encounteredWarning code: UInt, message: String) {
        super.jwplayer(player, encounteredWarning: code, message: message)
        print("Warning: \(code) - \(message)")
    }
    
    override func jwplayer(_ player: JWPlayer, encounteredAdError code: UInt, message: String) {
        super.jwplayer(player, encounteredAdError: code, message: message)
        print("Ad Error: \(code) - \(message)")
    }
    
    override func jwplayer(_ player: JWPlayer, encounteredAdWarning code: UInt, message: String) {
        super.jwplayer(player, encounteredAdWarning: code, message: message)
        print("Ad Warning: \(code) - \(message)")
    }
    
    override func jwplayer(_ player: JWPlayer, isBufferingWithReason reason: JWBufferReason) {
        super.jwplayer(player, isBufferingWithReason: reason)
        //        player.play()
        print("Buffering Reason:", reason)
    }
    
    //When Player is Paused
    override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) {
        super.jwplayer(player, didPauseWithReason: reason)
        if reason == .interaction{
            if let postID = vm.postID{
                PersistentStorage.shared.addKaraokeCount(postID: postID)
            }
        }
    }
    
    //When Player is Play
    override func jwplayer(_ player: JWPlayer, isPlayingWithReason reason: JWPlayReason) {
        super.jwplayer(player, isPlayingWithReason: reason)
        if reason == .interaction{
            if let postID = vm.postID{
                PersistentStorage.shared.addKaraokeCount(postID: postID)
            }
        }
    }
}

extension JWKaraokePlayerVC: UIDocumentPickerDelegate {

    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        deleteTemporaryFile()
    }
    
    // Method to delete the temporary file
    func deleteTemporaryFile() {
        let tempFileURL = vm.audioURLFromMP4!
        do {
            try FileManager.default.removeItem(at: tempFileURL)
            print("Temporary file deleted successfully.")
        } catch {
            print("Error deleting temporary file: \(error.localizedDescription)")
        }
    }
    func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        print("Document picker was cancelled")
    }
}
// MARK: - Full Screen Handling

extension JWKaraokePlayerVC {
    
    func playerViewControllerWillGoFullScreen(_ controller: JWPlayerViewController) -> JWFullScreenViewController? {
        //        controller.shouldEnterFullScreen = false
//        self.setDeviceOrientation(orientation: .portrait)
        self.player.stop()
        self.dismiss(animated: true)
        
        vm.updateKaraokeVideoView()
        
        print("playerViewControllerWillGoFullScreen")
        return nil
    }
    
    func playerViewControllerDidGoFullScreen(_ controller: JWPlayerViewController) {
        print("playerViewControllerDidGoFullScreen")
        
        return
    }
    
    func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) {
        print("playerViewControllerWillDismissFullScreen")
        
    }
    
    func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) {
//        print("playerViewControllerDidDismissFullScreen")
//        
//        self.dismissTapped?()
//        Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
//            self.player.stop()
//            controller.dismiss(animated: true)
//        }
    }
}

// MARK: - JWPlayerViewController Delegate Functions

extension JWKaraokePlayerVC {
    
    func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, controlBarVisibilityChanged isVisible: Bool, frame: CGRect) {
        self.backButton.isHidden = !isVisible
        //        backButton.isHidden = !isVisible
    }
    
    func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, sizeChangedFrom oldSize: CGSize, to newSize: CGSize) {
        // Handle size change if necessary
    }
    
    func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, screenTappedAt position: CGPoint) {
        // Handle screen tap if necessary
    }
    
    func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuOpenedWithItems items: [JWPlayerKit.JWPlayerItem], withMethod method: JWPlayerKit.JWRelatedInteraction) {
        print("Related items:", items)
    }
    
    func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuClosedWithMethod method: JWRelatedInteraction) {
        print("Related menu closed")
    }
    
    func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) {
        print("Item ", item)
    }
}

// MARK: - Google Ad Banner Delegate

extension JWKaraokePlayerVC : GADBannerViewDelegate{
    func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
        print("bannerViewDidReceiveAd")
        bannerView.backgroundColor = #colorLiteral(red: 0.01960784314, green: 0, blue: 0.2196078431, alpha: 1)
    }
    
    func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
        print("bannerView:didFailToReceiveAdWithError: \(error.localizedDescription)")
    }
    
    func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
        print("bannerViewDidRecordImpression")
    }
    
    func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
        print("bannerViewWillPresentScreen")
    }
    
    func bannerViewWillDismissScreen(_ bannerView: GADBannerView) {
        print("bannerViewWillDIsmissScreen")
    }
    
    func bannerViewDidDismissScreen(_ bannerView: GADBannerView) {
        print("bannerViewDidDismissScreen")
    }
}

//OLD Code
//private var audioEngine: AVAudioEngine!
//    private var audioFile: AVAudioFile!
//    private var audioPlayerNode: AVAudioPlayerNode!
//    private var recordedAudioFile: AVAudioFile!
//private var recordingURL: URL!
//
//private func setupAudioEngine() {
//    audioEngine = AVAudioEngine()
//    audioPlayerNode = AVAudioPlayerNode()
//
//    audioEngine.attach(audioPlayerNode)
//    let format = audioEngine.mainMixerNode.outputFormat(forBus: 0)
//    audioEngine.connect(audioPlayerNode, to: audioEngine.mainMixerNode, format: format)
//}
//
//private func startRecording() {
//    let format = audioEngine.mainMixerNode.outputFormat(forBus: 0)
//    let outputFileURL = FileManager.default.temporaryDirectory.appendingPathComponent("savedRecordedAudio.m4a")
//    recordingURL = outputFileURL
//    
//    do {
//        recordedAudioFile = try AVAudioFile(forWriting: outputFileURL, settings: format.settings)
//    } catch {
//        print("Error creating audio file for recording: \(error)")
//        return
//    }
//    
//    audioEngine.mainMixerNode.installTap(onBus: 0, bufferSize: 1024, format: format) { (buffer, time) in
//        do {
//            try self.recordedAudioFile?.write(from: buffer)
//        } catch {
//            print("Error writing audio buffer: \(error)")
//        }
//    }
//    
//    do {
//        try audioEngine.start()
//    } catch {
//        print("Error starting audio engine: \(error)")
//        return
//    }
//    
//    audioPlayerNode.play()
//}
//
//private func stopRecording() {
//        audioEngine.mainMixerNode.removeTap(onBus: 0)
//        audioPlayerNode.stop()
//        audioEngine.stop()
//    guard let mixedAudioURL = recordingURL else { return }
//    playAudio(at: mixedAudioURL)
////            presentDocumentPicker()
//    }
//
//private func playAudio(at url: URL) {
//    do {
//        let audioPlayer = try AVAudioPlayer(contentsOf: url)
//        audioPlayer.play()
//    } catch {
//        print("Error playing audio: \(error)")
//    }
//}
//
//private func getDocumentsDirectory() -> URL {
//    return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
//}
//
//private func presentDocumentPicker() {
//    guard let mixedAudioURL = recordingURL else { return }
//    DispatchQueue.main.async {
//        let documentPicker = UIDocumentPickerViewController(url: mixedAudioURL, in: .exportToService)
//        documentPicker.delegate = self
//        self.present(documentPicker, animated: true, completion: nil)
//    }
//}
//
//private func saveRecordingToFile() {
//    let fileManager = FileManager.default
//    let documentsURL = getDocumentsDirectory().appendingPathComponent("savedRecordedAudio.m4a")
//    
//    do {
//        if fileManager.fileExists(atPath: documentsURL.path) {
//            try fileManager.removeItem(at: documentsURL)
//        }
//        try fileManager.moveItem(at: recordingURL, to: documentsURL)
//        print("Recording saved to: \(documentsURL)")
//    } catch {
//        print("Error saving recording: \(error)")
//    }
//}
