//
//  MoreVM.swift
//  WOKA
//
//  Created by MacBook Pro on 10/06/24.
//

import UIKit
import AVFoundation
import GoogleMobileAds

enum PlayerStatus{
    case play
    case loading
    case pause
    case resume
    case stopped
}

var currentTimePlayer = Int()
var totalTime = Int()

class MoreVM{
    
    weak var vc : MoreVC!
    
    var blogData = [BlogDM.Blog]()
    
    var songData = [SongBlogDM.PaintDatum]()

    var player : AVPlayer?
    var playerObserver: NSKeyValueObservation?
    var playerStatus = PlayerStatus.loading
    
    var currentIndexPlayingSong : Int?
    var headerBannerView = GADBannerView()

    
    func initView(){
        getBLogs()
        setupAudioSession()
        getSong()
        setupCell()
        vc.songTableView.showsVerticalScrollIndicator = false
        vc.songTableView.showsHorizontalScrollIndicator = false
        
        vc.homeBtn.addTapGesture { [weak self] in
            guard let self else{return}
            DispatchQueue.main.async{
                self.vc.dismiss(animated: true) {
                    PersistentStorage.shared.addOthersCount()
                }
            }
        }
        
        /*
         First check if webSeries ad is present via slug, then check for Local Ads, if not then check google ads.
         */
        if let adsData = AuthFunc.shareInstance.adsData, let moreAd = adsData.result?.filter({$0.slug == AdsEnum.more.rawValue}).first{
            
            // check if ads data contains LocalAD for webseries
            if let advertisement = moreAd.advertisement,let bannerImage = advertisement.bannerImage{
                vc.customAdImage.imageURL(bannerImage, color: .white)
                vc.customAdImage.alpha = 0
                let height = UIScreen.main.bounds.width * 0.55
                vc.customAdHeight.constant = height
                vc.trailerTask.isHidden = true
                vc.customAdImage.isHidden = false
                
                UIView.animate(withDuration: 0.2, animations: { [weak self] in
                    guard let self else{return}
                    vc.customAdImage.alpha = 1
                })
                
                vc.customAdImage.addTapGesture {
                    if let adID = moreAd.id{
                        PersistentStorage.shared.addAdsCount(adID: adID ,clicks: 1)
                    }
                    if let adLink = moreAd.advertisement?.adLink ,let url = URL(string: adLink), UIApplication.shared.canOpenURL(url) {
                        UIApplication.shared.open(url)
                    }
                }
            }else if moreAd.googleAd != nil{
                /*
                 Show google ads with dispatch queue.
                 */
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: { [weak self] in
                    guard let self else{return}
                    AdReusable.sharedInstance.setupBannerAd(bannerView: headerBannerView, in: vc.trailerTask, adUnitID: K.GoogleAdIDs.splashBanner2, viewController: self.vc, height: 5, width: 15)
                })
            }
        }
    }
    
    func setupAudioSession() {
        let session = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(.playback, mode: .spokenAudio)
            try session.setActive(true)
        } catch {
            print("Failed to set up audio session")
        }
    }
    
    func observePlayer() {
        playerObserver = self.player?.observe(\.timeControlStatus, options: [.new, .old], changeHandler: { [weak self] player, change in
            guard let self = self else { return }
            switch player.timeControlStatus {
            case .playing:
                print("Player is playing OOO")
                self.playerStatus = .play
                vc.songTableView.reloadRows(at: [IndexPath(row: currentIndexPlayingSong ?? 0, section: 0)], with: .none)
            case .paused:
                print("Player is paused OOO")
//                self.playerStatus = .pause
                if self.player?.currentTime() == self.player?.currentItem?.duration {
                    print("Player finished playing")
                    self.playerStatus = .stopped
                    if let currentIndexPlayingSong{
                        self.vc.songTableView.reloadRows(at: [IndexPath(row: currentIndexPlayingSong, section: 0)], with: .none)
                        self.currentIndexPlayingSong = nil
                    }else{
                        self.vc.songTableView.reloadData()
                    }
                } else {
                    print("Player is paused")
                    self.playerStatus = .pause
                }
            case .waitingToPlayAtSpecifiedRate:
                print("Player is waiting to play at specified rate OOO")
                self.playerStatus = .loading
            @unknown default:
                print("Unknown player status OOO")
            }
        })
    }
    
    func setupCell(){
        vc.blogsCollectionView.register(UINib(nibName: K.CellIdentifier.Home.blogsCell, bundle: nil), forCellWithReuseIdentifier: K.CellIdentifier.Home.blogsCell)
        vc.blogsCollectionView.delegate = vc.self
        vc.blogsCollectionView.dataSource = vc.self
        
        vc.songTableView.register(UINib(nibName: K.CellIdentifier.Home.songListCell, bundle: nil), forCellReuseIdentifier: K.CellIdentifier.Home.songListCell)
        vc.songTableView.delegate = vc.self
        vc.songTableView.dataSource = vc.self
    }
    
    
    // MARK: - Get BLogs Data

    func getBLogs(){
        vc.blogActivityIndicator.startAnimating()
        NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Home.blogs, method: .get) { [weak self](result : Result<BaseResponseModel<BlogDM>, NetworkManager.APIError>) in
            guard let self else{return}
            Utilities.dismissProgressHUD()
            switch result{
            case .success(let data):
                switch data.success{
                case 0:
                    /*
                     Error
                     */
                    vc.blogActivityIndicator.stopAnimating()
                    vc.blogRetryBtn.isHidden = false
                    vc.toast(msg: data.message ?? "Unrecognised error" , time: 1.5)
                case 1:
                    vc.blogActivityIndicator.stopAnimating()
                    vc.blogRetryBtn.isHidden = true
                    guard let data = data.data?.blogs else{return}
                    blogData = data
                    vc.blogsCollectionView.reloadData()
                default:
                    vc.blogActivityIndicator.stopAnimating()
                    vc.blogRetryBtn.isHidden = false
                }
            case .failure(let error):
                vc.blogActivityIndicator.stopAnimating()
                vc.blogRetryBtn.isHidden = false
                vc.toast(msg: error.localizedDescription , time: 1.5)
            }
        }
    }
    
    func getSong(){
        vc.songActivityIndicator.startAnimating()
        NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Home.song_listing, method: .post) { [weak self](result : Result<BaseResponseModel<SongBlogDM>, NetworkManager.APIError>) in
            guard let self else{return}
            Utilities.dismissProgressHUD()
            switch result{
            case .success(let data):
                switch data.success{
                case 0:
                    /*
                     Error
                     */
                    vc.songActivityIndicator.stopAnimating()
                    vc.songRetry.isHidden = false
                    vc.toast(msg: data.message ?? "Unrecognised error" , time: 1.5)
                case 1:
                    vc.songActivityIndicator.stopAnimating()
                    vc.songRetry.isHidden = true
                    guard let data = data.data?.paintData else{return}
                    songData = data
                    vc.songTableView.reloadData()
                    break
                default:
                    vc.songActivityIndicator.stopAnimating()
                    vc.songRetry.isHidden = false
                }
            case .failure(let error):
                vc.songActivityIndicator.stopAnimating()
                vc.songRetry.isHidden = false
                vc.toast(msg: error.localizedDescription , time: 1.5)
            }
        }
    }
}

// MARK: - Handle Media Player for background

extension MoreVM{
    
    func handleInlinePlay(indexPath : Int){
//        guard let self = self.vc else{return}
        PersistentStorage.shared.addOthersCount()
        /*
         this will declare if the song is playing or not
         */
        if let playingIndex = currentIndexPlayingSong {
            if indexPath == playingIndex{ // if same row is selected pause the row
                print(playerStatus)
                switch playerStatus{
                case .play: // if player is playing pause it.
                    print("Player is playing")
                    player?.pause()
                    playerStatus = .pause
                    vc.songTableView.reloadRows(at: [IndexPath(row: currentIndexPlayingSong!, section: 0)], with: .none)
                case .pause:
                    player?.play()
                    playerStatus = .resume
                    vc.songTableView.reloadRows(at: [IndexPath(row: currentIndexPlayingSong!, section: 0)], with: .none)
                case .loading:
                    print("Player is loading")
                case .resume:
                    print("Player is resume")
                default:
                    break
                }
            }else{
                /*
                 this means other cell was playing now stop it and play this new cell
                 first reload the playing cell and pause the audio
                 */
                //Reset Old Cell
                playerStatus = .stopped
                vc.songTableView.reloadRows(at: [IndexPath(row: currentIndexPlayingSong!, section: 0)], with: .none)
                
                //Update new cell
                currentIndexPlayingSong = indexPath
                playerStatus = .loading
                currentTimePlayer = 0
                vc.songTableView.reloadRows(at: [IndexPath(row: indexPath, section: 0)], with: .none)
                let data = songData[indexPath]
                vc.startPlaying(song: data, at: IndexPath(row: indexPath, section: 0))
                print("Other cell playing")
            }
        }else{
            // if there is no playing audio before
            playerStatus = .loading
            currentIndexPlayingSong = indexPath
            currentTimePlayer = 0
            vc.songTableView.reloadRows(at: [IndexPath(row: indexPath, section: 0)], with: .none)
            let data = songData[indexPath]
            vc.startPlaying(song: data, at: IndexPath(row: indexPath, section: 0))
            print("First Play")
        }
    }
    
    func stopMPNowPlayin(){
        MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]
        UIApplication.shared.endReceivingRemoteControlEvents()
        let commandCenter = MPRemoteCommandCenter.shared()
        
        // Disable play/pause commands
        commandCenter.playCommand.removeTarget(nil)
        commandCenter.pauseCommand.removeTarget(nil)
    }
    
    func setupNowPlayingInfo(songTitle : String) {
        let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
        var nowPlayingInfo: [String: Any] = [:]

        // Set the media title, artist, and album name
        
        nowPlayingInfo[MPMediaItemPropertyTitle] = songTitle
        nowPlayingInfo[MPMediaItemPropertyArtist] = "WOKA Songs"
        nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = ""
        nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = true

        if let originalImage = UIImage(named: "ExploreWoka") {
            
            let artworkImage = imageWithBackground(color: #colorLiteral(red: 0.4495816827, green: 0.2344398499, blue: 0.8120074868, alpha: 1), originalImage: originalImage)
            
            let artwork = MPMediaItemArtwork(boundsSize: originalImage.size) { size in
                return artworkImage ?? originalImage
            }
            
            nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork

        }
        
        // Set the duration and current playback position
        if let currentItem = player?.currentItem {
            nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = currentItem.asset.duration.seconds
            nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player?.currentTime().seconds
            nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player?.rate
        }
        
        // Assign the nowPlayingInfo to the center
        nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo
        
//        updateNowPlayingInfo()
    }
    
    func setupRemoteCommandCenter() {
        let commandCenter = MPRemoteCommandCenter.shared()

        // Enable play command
        commandCenter.playCommand.addTarget { [weak self] event in
            guard let self else{return .commandFailed}

            if player?.rate == 0.0 {
                player?.play()
                return .success
            }
            return .commandFailed
        }

        // Enable pause command
        commandCenter.pauseCommand.addTarget { [weak self] event in
            guard let self else{return .commandFailed}

            if player?.rate == 1.0 {
//                player?.pause()
                if let currentIndexPlayingSong{
                    handleInlinePlay(indexPath: currentIndexPlayingSong)
                }
                return .success
            }
            return .commandFailed
        }
        
        // Enable next and previous track commands if needed
//        commandCenter.nextTrackCommand.isEnabled = true
//        commandCenter.previousTrackCommand.isEnabled = true
//
//        
//        if let currentIndexPlayingSong = currentIndexPlayingSong{
//            if currentIndexPlayingSong == 0{
//                commandCenter.previousTrackCommand.isEnabled = false
//            }
//            
//            if currentIndexPlayingSong == songData.count - 1{
//                commandCenter.nextTrackCommand.isEnabled = false
//            }
//        }
//        
//        
//        // Enable next command
//        commandCenter.nextTrackCommand.addTarget { [unowned self] event in
//            commandCenter.previousTrackCommand.isEnabled = true
//            if let currentIndexPlayingSong = currentIndexPlayingSong{
//                if currentIndexPlayingSong == songData.count - 1{
//                    //if the song played is the last index disable the next track
//                    commandCenter.nextTrackCommand.isEnabled = false
//                    return .commandFailed
//                }
//                
//                handleInlinePlay(indexPath: currentIndexPlayingSong + 1)
//                setupNowPlayingInfo(songTitle: songData[currentIndexPlayingSong + 1].title ?? "WOKA")
//                updateNowPlayingInfo()
//                return .success
//            }
//            return .commandFailed
//        }
//        
//        // Enable pause command
//        commandCenter.previousTrackCommand.addTarget { [unowned self] event in
//            commandCenter.nextTrackCommand.isEnabled = true
//            if let currentIndexPlayingSong = currentIndexPlayingSong{
//                if currentIndexPlayingSong == 0{
//                    //if the song played is the last index disable the previous track
//                    commandCenter.previousTrackCommand.isEnabled = false
//                    return .commandFailed
//                }
//                
//                setupNowPlayingInfo(songTitle: songData[currentIndexPlayingSong - 1].title ?? "WOKA")
//                handleInlinePlay(indexPath: currentIndexPlayingSong - 1)
//                updateNowPlayingInfo()
//                return .success
//            }
//            return .commandFailed
//        }

    }
    
    func imageWithBackground(color: UIColor, originalImage: UIImage) -> UIImage? {
        let size = originalImage.size
        UIGraphicsBeginImageContextWithOptions(size, false, originalImage.scale)
        let rect = CGRect(origin: CGPoint.zero, size: size)
        
        // Fill the background with a color
        color.setFill()
        UIRectFill(rect)
        
        // Draw the original image on top
        originalImage.draw(in: rect)
        
        // Capture the new image with background
        let imageWithBackground = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return imageWithBackground
    }
    
    func updateNowPlayingInfo() {
        if let currentItem = player?.currentItem {
            var nowPlayingInfo = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]
            nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = player?.currentTime().seconds
            nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player?.rate
            MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
        }
    }
}


import UIKit
import MediaPlayer

extension UIView {
    
    private struct AssociatedKeys {
        static var loadingView = "loadingView"
    }
    
    private var loadingView: LoadingView? {
        get {
            return objc_getAssociatedObject(self, AssociatedKeys.loadingView) as? LoadingView
        }
        set {
            objc_setAssociatedObject(self, AssociatedKeys.loadingView, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    func showLoading() {
        if loadingView == nil {
            let newLoadingView = LoadingView(frame: self.bounds)
            newLoadingView.translatesAutoresizingMaskIntoConstraints = false
            self.addSubview(newLoadingView)
            NSLayoutConstraint.activate([
                newLoadingView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                newLoadingView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                newLoadingView.topAnchor.constraint(equalTo: self.topAnchor),
                newLoadingView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
            ])
            loadingView = newLoadingView
        }
        loadingView?.startLoading()
    }
    
    func hideLoading() {
        loadingView?.stopLoading()
    }
}

class LoadingView: UIView {
    
    private var activityIndicator: UIActivityIndicatorView!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }
    
    private func setupView() {
        self.backgroundColor = .clear
        
        activityIndicator = UIActivityIndicatorView(style: .medium)
        activityIndicator.translatesAutoresizingMaskIntoConstraints = false
        activityIndicator.color = .white
        self.addSubview(activityIndicator)
        
        NSLayoutConstraint.activate([
            activityIndicator.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            activityIndicator.centerYAnchor.constraint(equalTo: self.centerYAnchor),
            activityIndicator.heightAnchor.constraint(equalToConstant: self.frame.height - 10),
            activityIndicator.widthAnchor.constraint(equalToConstant: self.frame.width - 10)
        ])
    }
    
    func startLoading() {
        activityIndicator.startAnimating()
        self.isHidden = false
    }
    
    func stopLoading() {
        activityIndicator.stopAnimating()
        self.isHidden = true
    }
}
