import UIKit
import AVFoundation
import AVKit
import AssetsLibrary
import Photos

class PlayerViewController: UIViewController {
    
    //MARK: - Outlet
    
    @IBOutlet weak var lblTitle: UILabel!
    @IBOutlet weak var ViewTitle: UIView!
    @IBOutlet weak var ViewPlayer: UIView!
    @IBOutlet weak var ViewBottom: UIView!
    @IBOutlet weak var btnbackword: UIButton!
    @IBOutlet weak var btnForword: UIButton!
    @IBOutlet weak var btnPlay: UIButton!
    @IBOutlet weak var lblTimeRemaining: UILabel!
    @IBOutlet weak var SliderSeek: UISlider!
    @IBOutlet weak var progressView: UIProgressView!
    
    //MARK: - Properteis
    
    var avPlayer = AVPlayer()
    var avPlayerLayer: AVPlayerLayer!
    var PlayTemp = false
    var index = Int()
    var tableDataSource1 = [Video]()
    let invisibleButton = UIButton()
    var timeObserver: AnyObject!
    var CurrentTime : CMTime!
    var playerRateBeforeSeek: Float = 0
    var VedioPlayerItem : AVPlayerItem!
    var urlString : String!
    

    // MARK: - ViewController Method
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Rotate
        
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.shouldRotate = true
        
        // Vedio Title
        
        let title: Video = tableDataSource1[index]
        let TitleName  =  title.title
        lblTitle.text = TitleName
        
        //  Notification Center
        
        NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
        
        print(tableDataSource1)
        print(index)
        
        let video: Video = tableDataSource1[index]
        let url  = URL(string: video.url)
        urlString = video.url
        
      // check file exist or not in file manager
        
        let theFileName = (video.url as NSString).lastPathComponent
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
        let filePath="\(documentsPath)/\(theFileName)"
        print(filePath)

        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: filePath) {

            print(filePath)

            VedioPlayerItem = AVPlayerItem(url:NSURL(fileURLWithPath: filePath) as URL)
        }
        else
        {
             VedioPlayerItem = AVPlayerItem(url: url!)
        }
      
        // setup AvPlayer

        //let playerItem = AVPlayerItem(url: url!)
        avPlayer = AVPlayer(playerItem: VedioPlayerItem)
        avPlayerLayer = AVPlayerLayer(player: avPlayer)
        self.ViewPlayer.layer.addSublayer(avPlayerLayer)
        avPlayer.isMuted = false
        avPlayer.play()
        
        // Setup invisible Button
        
        ViewPlayer.addSubview(invisibleButton)
        invisibleButton.addTarget(self, action: #selector(invisibleButtonTapped),
                                  for: .touchUpInside)
       
        // time Interval
        
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0, 10)
        timeObserver = avPlayer.addPeriodicTimeObserver(forInterval: timeInterval,queue: DispatchQueue.main) {
            (elapsedTime: CMTime) -> Void in
            self.observeTime(elapsedTime)
            } as AnyObject!
        
        // Setup Slider
        
        SliderSeek.addTarget(self, action: #selector(sliderBeganTracking1),
                             for: .touchDown)
        SliderSeek.addTarget(self, action: #selector(sliderEndedTracking),
                             for: .touchUpInside)
        SliderSeek.addTarget(self, action: #selector(sliderEndedTracking),
                             for: .touchUpOutside)
        SliderSeek.addTarget(self, action: #selector(sliderValueChanged),
                             for: .valueChanged)
       
        SliderSeek.setThumbImage(UIImage(named:"ic_playhead_default"), for: UIControlState())


        // Setup navigation
        
        self.title = "Player"
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 126/255, green: 174/255, blue: 0/255, alpha: 1)
        self.navigationController?.navigationBar.tintColor = UIColor.black
       
        // Setup Progress View
        
        customizeProgressView()
   }
  
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        // remove Time Observer
        
        avPlayer.removeTimeObserver(timeObserver!)
       
    }
    
    override func viewWillAppear(_ animated: Bool) {
    
      super.viewWillAppear(animated)
    
      self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(BackbuttonTapped))
  
     avPlayer.play()
  
    }
    
    override func viewWillLayoutSubviews() {
        
       // Layout subviews manually
        
       avPlayerLayer.frame = ViewPlayer.bounds
       invisibleButton.frame = ViewPlayer.bounds
    }

    
    
    //MARK: - Action
    
    @IBAction func backwordAction(_ sender: UIButton) {
        previousTrack()
    }
    
    
    @IBAction func forwordAction(_ sender: UIButton) {
        nextTrack()
    }
    
    
    @IBAction func playAction(_ sender: UIButton)
    {
        let playerIsPlaying = avPlayer.rate > 0
        if playerIsPlaying {
            avPlayer.pause()
            avPlayer.isMuted = true
            btnPlay.setImage( imageLiteral(resourceName: "play-button"), for:UIControlState.normal)
            
        } else {
            avPlayer.play()
            avPlayer.isMuted = false
            btnPlay.setImage( imageLiteral(resourceName: "pause"), for:UIControlState.normal)
        }

    }
    
    // MARK: - Custom Method
    
    func customizeProgressView() {
        progressView.layer.cornerRadius = 2
        progressView.layer.masksToBounds = true
       
    }
    
    // Back Button
    
    @objc func BackbuttonTapped(){

    UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "Orientation")
        self.navigationController?.popViewController(animated: true)
        avPlayer.pause()
        avPlayer.isMuted = true
        
    }
    
    // invisible Button
    
    @objc func invisibleButtonTapped(sender: UIButton) {
        let playerIsPlaying = avPlayer.rate > 0
        if playerIsPlaying {
            avPlayer.pause()
            avPlayer.isMuted = true
             btnPlay.setImage( imageLiteral(resourceName: "play-button"), for:UIControlState.normal)
        } else {
            avPlayer.play()
            avPlayer.isMuted = false
            btnPlay.setImage( imageLiteral(resourceName: "pause"), for:UIControlState.normal)
        }
    }
    
    // previous
    
    func previousTrack() {
        lblTimeRemaining.text = "00:00"
       SliderSeek.setValue(00.00, animated: true)
        if index - 1 < 0 {
            index = (tableDataSource1.count - 1) < 0 ? 0 : (tableDataSource1.count - 1)
            print(index)
        } else {
            index -= 1
            print(index)
        }
        playTrack()
    }
    
    // play
    
    func playTrack() {
        let video: Video = tableDataSource1[index]
        let url  = URL(string: video.url)
        let theFileName = (video.url as NSString).lastPathComponent

        // check file exist or not in file manager
        
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
        let filePath="\(documentsPath)/\(theFileName)"
        print(filePath)
        
        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: filePath) {
            
            print(filePath)
            
            VedioPlayerItem = AVPlayerItem(url:NSURL(fileURLWithPath: filePath) as URL)
        }
        else
        {
            VedioPlayerItem = AVPlayerItem(url: url!)
        }
        
        let TitleName  =  video.title
        lblTitle.text = TitleName
        if tableDataSource1.count > 0 {
            avPlayer.replaceCurrentItem(with: VedioPlayerItem)
            avPlayer.play()
        }
    }
    
    // next
    
    func nextTrack() {
         lblTimeRemaining.text = "00:00"
         SliderSeek.setValue(00.00, animated: true)
        if index + 1 == tableDataSource1.count{
            index = 0
        }
       else if index + 1 > tableDataSource1.count {
            index = 0
            print(index)
        } else {
            index += 1;
            print(index)
        }
        playTrack()
    }
    
    // deinit
    
    deinit {
        avPlayer.removeTimeObserver(timeObserver)
        NotificationCenter.default.removeObserver(self)
    }
    
    // update Time Label
    
    func updatePlayerTimer(_ elapsedTime: Float64, duration: Float64) {
       lblTimeRemaining.text = String(format: "%02d:%02d", ((lround(elapsedTime) / 60) % 60), lround(elapsedTime) % 60)
    }
    
    
    // observe Time
    
    fileprivate func observeTime(_ elapsedTime: CMTime) {
      
        let duration = CMTimeGetSeconds(avPlayer.currentItem!.duration)
        if (duration.isFinite) {
           let elapsedTime = CMTimeGetSeconds(elapsedTime)
           updatePlayerTimer(elapsedTime,duration: duration)
           updatePlayerSlider(elapsedTime,duration: duration)
        }
    }
  
    // slider Began Tracking

    @objc func sliderBeganTracking1(slider: UISlider) {
        playerRateBeforeSeek = avPlayer.rate
        avPlayer.pause()
    }
    
  
    // slider Ended Tracking

    @objc func sliderEndedTracking(slider: UISlider) {
        
        if let duration = self.avPlayer.currentItem?.duration {
            let videoDuration = CMTimeGetSeconds(duration)
            let elapsedTime: Float64 = videoDuration * Float64(slider.value)
            updatePlayerTimer(elapsedTime,duration: videoDuration)
            
            avPlayer.seek(to: CMTimeMakeWithSeconds(elapsedTime, 10), completionHandler: { (completed: Bool) -> Void in
         
                if (self.playerRateBeforeSeek > 0) {
                    if (self.avPlayer != nil)  {
                        self.avPlayer.play()
                }
                }})
        }
        SliderSeek.setThumbImage(UIImage(named:"ic_playhead_default"), for: UIControlState())
    }
    
    // slider Value Changed

    @objc func sliderValueChanged(slider: UISlider) {

        if let duration = self.avPlayer.currentItem?.duration {
            let videoDuration = CMTimeGetSeconds(duration)
            let elapsedTime: Float64 = videoDuration * Float64(slider.value)
           updatePlayerTimer(elapsedTime,duration: videoDuration)
        }
        SliderSeek.setThumbImage(UIImage(named:"ic_playhead_pressed"), for: UIControlState())
    }
    
    // player Item Duration
    
    private func playerItemDuration() -> CMTime {
        let thePlayerItem = avPlayer.currentItem
        if thePlayerItem?.status == .readyToPlay {
            return thePlayerItem!.duration
        }
        return kCMTimeInvalid
    }

    // player Item Did Reach End
    
    @objc func playerItemDidReachEnd(notification: NSNotification) {
        if notification.object as? AVPlayerItem  == avPlayer.currentItem {
            
            avPlayer.seek(to: kCMTimeZero)
        
            let urrl = ((avPlayer.currentItem?.asset) as! AVURLAsset).url
            let urlString : String = String(describing: urrl)
            
            // get last path of URL
            let theFileName = (urlString as NSString).lastPathComponent
        
            DispatchQueue.global(qos: .background).async {
                if let url : URL = urrl,
                    let urlData = NSData(contentsOf: url)
                {
                    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
                    let filePath="\(documentsPath)/\(theFileName)"
                    print(filePath)

                    let fileManager = FileManager.default
                    if fileManager.fileExists(atPath: filePath) {
                        print(filePath)
                    }
                    else
                    {
                    DispatchQueue.main.async {
                        urlData.write(toFile: filePath, atomically: true)
                        PHPhotoLibrary.shared().performChanges({
                            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
                        }) { completed, error in
                            if completed {
                                print(filePath)
                                print("Video is saved!")
                            }
                            if (error != nil) {
                                print("Video is not saved!")
                                print(error?.localizedDescription)
                      }
                    }
                  }
                }
              }
            }
          }
          nextTrack()
    }
    // update Player Slider
    
    func updatePlayerSlider(_ elapsedTime: Float64, duration: Float64) {
        
        let progress =  elapsedTime / duration
        SliderSeek.setValue(Float(progress), animated: false)
        
    }
    
   // URLAsset function
    
    lazy var asset: AVURLAsset = {
        let video: Video = tableDataSource1[index]
        let currVedioURL  = URL(string: video.url)
        var asset : AVURLAsset = AVURLAsset(url: currVedioURL!)
        asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main)
        print(currVedioURL!)
        return asset
    }()
    
    //MARK: - Orientation

    override var shouldAutorotate: Bool {
        return false
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask{
        return .landscapeLeft
    }
    
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{
        return .landscapeLeft
    }
    
  
}

//MARK: AVAssetResourceLoaderDelegate

extension PlayerViewController : AVAssetResourceLoaderDelegate {
    
}




Comments