--- /dev/null
+//
+// PlayerViewController.swift
+// WolneLektury
+//
+// Created by Pawel Dabrowski on 07/09/2018.
+// Copyright © 2018 Fundacja Nowoczesna Polska. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+import MediaPlayer
+import Kingfisher
+
+class PlayerViewController: WLViewController {
+
+ @IBOutlet weak var titleLabel: UILabel!
+ @IBOutlet weak var bgImageView: UIImageView!
+ @IBOutlet weak var bgOverlayView: UIView!
+ @IBOutlet weak var miniatureImageView: UIImageView!
+ @IBOutlet weak var tableView: UITableView!
+ @IBOutlet weak var backButton: UIButton!
+ @IBOutlet weak var toggleListButton: UIButton!
+ @IBOutlet weak var nextButton: UIButton!
+ @IBOutlet weak var prevButton: UIButton!
+ @IBOutlet weak var forwardButton: UIButton!
+ @IBOutlet weak var rewindButton: UIButton!
+ @IBOutlet weak var playPauseButton: UIButton!
+ @IBOutlet weak var trackNumberLabel: UILabel!
+ @IBOutlet weak var trackTitleLabel: UILabel!
+ @IBOutlet weak var trackCurrentTimeLabel: UILabel!
+ @IBOutlet weak var trackTimeLabel: UILabel!
+ @IBOutlet weak var progressSlider: UISlider!
+ @IBOutlet weak var miniatureImageWidthConstraint: NSLayoutConstraint!
+ @IBOutlet weak var trackTitleLabelTopConstraint: NSLayoutConstraint!
+
+ var bookDetailsModel: BookDetailsModel!
+ var mediaModels: [MediaModel]!
+ var selectedRow: Int?
+
+ static func instance(bookDetailsModel: BookDetailsModel) -> PlayerViewController{
+ let controller = PlayerViewController.instance()
+ controller.bookDetailsModel = bookDetailsModel
+ controller.mediaModels = bookDetailsModel.getAudiobookMediaModels()
+ return controller
+ }
+
+ open override var preferredStatusBarStyle : UIStatusBarStyle {
+ return .lightContent
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ tableView.separatorStyle = .none
+ tableView.isHidden = true
+
+ if UIScreen.main.bounds.size.width == 320 || UIScreen.main.bounds.size.height == 320 {
+ miniatureImageWidthConstraint.constant = 100
+ }
+
+ bgOverlayView.alpha = 0.7
+ bgOverlayView.backgroundColor = bookDetailsModel.bgColor
+ let titleAttributedText = bookDetailsModel.getAttributedAuthorAndTitle(titleFont: UIFont.systemFont(ofSize: 21, weight: .light), descFont: UIFont.systemFont(ofSize: 28, weight: .light))
+ titleLabel.attributedText = titleAttributedText
+
+ if let bookDetails = PlayerController.shared.currentBookDetails, bookDetails.slug == bookDetailsModel.slug {
+ PlayerController.shared.startOrContinuePlaying(bookDetailsModel: bookDetailsModel, delegate: self)
+ }
+ else {
+ PlayerController.shared.stopAndClear()
+ PlayerController.shared.preparePlayer(bookDetailsModel: bookDetailsModel, delegate: self, trackIndex: 0)
+ }
+
+ if mediaModels.count < 2 {
+ trackNumberLabel.isHidden = true
+ trackNumberLabel.text = ""
+ toggleListButton.isHidden = true
+ trackTitleLabelTopConstraint.constant = 10
+ }
+
+ refreshButtonsVisibility()
+
+ if let url = bookDetailsModel.getCoverThumbUrl(){
+ ImageDownloader.default.downloadImage(with: url, options: [], progressBlock: nil) {
+ [weak self] (image, error, url, data) in
+ if let image = image{
+ self?.bgImageView.image = image
+ self?.miniatureImageView.image = image
+ PlayerController.shared.setCoverImage(image: image)
+ }
+ }
+ }
+ }
+
+ // ############################################
+ // MARK: - Private
+ // ############################################
+
+ private func toggleList() {
+ tableView.isHidden = !tableView.isHidden
+ }
+
+ private func startNextTrack() {
+ PlayerController.shared.playNextAudio()
+ }
+
+ private func startPrevTrack() {
+ PlayerController.shared.playPreviousAudio()
+ }
+
+ //This returns song length
+ private func calculateTimeFromNSTimeInterval(_ duration:TimeInterval) ->(hour: String, minute:String, second:String){
+ let hour_ = abs(Int(duration)/3600)
+ let minute_ = abs(Int((duration/60).truncatingRemainder(dividingBy: 60)))
+ let second_ = abs(Int(duration.truncatingRemainder(dividingBy: 60)))
+
+ var hour = hour_ > 9 ? "\(hour_)" : "0\(hour_)"
+ if hour_ == 0 {
+ hour = ""
+ }
+ let minute = minute_ > 9 ? "\(minute_)" : "0\(minute_)"
+ let second = second_ > 9 ? "\(second_)" : "0\(second_)"
+ return (hour, minute,second)
+ }
+
+ fileprivate func updateCurrentTime(timeInterval: TimeInterval?) {
+
+ var ti = timeInterval
+ if ti == nil {
+ ti = PlayerController.shared.getCurrentTime()
+ }
+
+ if let ti = ti {
+ let timeIntervalFloat = Float(ti)
+ progressSlider.value = timeIntervalFloat
+ let time = calculateTimeFromNSTimeInterval(ti)
+ if time.hour.count == 0 {
+ trackCurrentTimeLabel.text = "\(time.minute):\(time.second)"
+ }
+ else {
+ trackCurrentTimeLabel.text = "\(time.hour):\(time.minute):\(time.second)"
+ }
+ }
+ }
+
+ func refreshButtonsVisibility(){
+
+ prevButton.isHidden = true
+ nextButton.isHidden = true
+
+ let currentAudiobookIndex = PlayerController.shared.currentAudiobookIndex
+ let allMediaCount = mediaModels.count
+
+ if currentAudiobookIndex > 0{
+ prevButton.isHidden = false
+ }
+ if allMediaCount > currentAudiobookIndex + 1 {
+ nextButton.isHidden = false
+ }
+ }
+
+ // ############################################
+ // MARK: - Action
+ // ############################################
+
+ @IBAction func backButtonAction(sender: UIButton) {
+ PlayerController.shared.delegate = nil
+ navigationController?.popViewController(animated: true)
+ }
+
+ @IBAction func toggleListButtonAction(sender: UIButton) {
+ toggleList()
+ }
+
+ @IBAction func nextButtonAction(sender: UIButton) {
+ PlayerController.shared.playNextAudio()
+ }
+
+ @IBAction func prevButtonAction(sender: UIButton) {
+ PlayerController.shared.playPreviousAudio()
+ }
+
+ @IBAction func forwardButtonAction(sender: UIButton) {
+ PlayerController.shared.forward()
+ }
+
+ @IBAction func rewindButtonAction(sender: UIButton) {
+ PlayerController.shared.rewind()
+ }
+
+ @IBAction func playPauseButtonAction(sender: UIButton) {
+ let player = PlayerController.shared
+ if player.isPlaying() {
+ player.pauseAudioPlayer()
+ }
+ else {
+ if player.audioPlayer == nil {
+ player.startOrContinuePlaying(bookDetailsModel: bookDetailsModel, delegate: self)
+ }
+ else {
+ player.playAudio()
+ }
+ }
+ playPauseButton.setImage(player.isPlaying() ? #imageLiteral(resourceName: "player_controls_pause") : #imageLiteral(resourceName: "player_controls_play"), for: .normal)
+ }
+
+ @IBAction func progressSliderAction(sender: UISlider) {
+ PlayerController.shared.changeTime(timeInterval: TimeInterval(sender.value))
+ }
+}
+
+extension PlayerViewController: UITableViewDataSource {
+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ return mediaModels.count
+ }
+
+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ let cell = tableView.dequeueReusableCell(withIdentifier: "PlayerItemTableViewCell", for: indexPath) as! PlayerItemTableViewCell
+ let isSelected = PlayerController.shared.currentAudiobookIndex == indexPath.row
+ cell.setup(mediaModel: mediaModels[indexPath.row], isPlaying: isSelected)
+ return cell
+ }
+}
+
+extension PlayerViewController: UITableViewDelegate {
+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+ if mediaModels.count > indexPath.row {
+
+ PlayerController.shared.startPlaying(bookDetailsModel: bookDetailsModel, delegate: self, trackIndex: indexPath.row)
+ }
+ }
+}
+
+extension PlayerViewController: PlayerControllerDelegate {
+
+ func playerControllerDelegateTrackChanged() {
+
+ let player = PlayerController.shared
+ progressSlider.maximumValue = Float(player.audioLength)
+
+ updateCurrentTime(timeInterval: player.getCurrentTime())
+ trackNumberLabel.text = String(format: "player_chapter_number".localized, player.currentAudiobookIndex + 1)
+
+ if let currentModel = player.getCurentAudiobookMediaModel() {
+ trackTitleLabel.text = currentModel.name
+ let time = calculateTimeFromNSTimeInterval(player.audioLength)
+ if time.hour.count == 0 {
+ trackTimeLabel.text = "\(time.minute):\(time.second)"
+ }
+ else {
+ trackTimeLabel.text = "\(time.hour):\(time.minute):\(time.second)"
+ }
+ }
+
+ playPauseButton.setImage(player.isPlaying() ? #imageLiteral(resourceName: "player_controls_pause") : #imageLiteral(resourceName: "player_controls_play"), for: .normal)
+
+ let newSelectedIndex = IndexPath(row: PlayerController.shared.currentAudiobookIndex, section: 0)
+ tableView.selectRow(at: newSelectedIndex, animated: true, scrollPosition: .middle)
+
+ refreshButtonsVisibility()
+ }
+
+ func playerControllerDelegateUpdatePlayerProgress(timeInterval: TimeInterval) {
+ updateCurrentTime(timeInterval: timeInterval)
+ }
+
+ func playerControllerDelegatePlayStateChanged() {
+ playPauseButton.setImage(PlayerController.shared.isPlaying() ? #imageLiteral(resourceName: "player_controls_pause") : #imageLiteral(resourceName: "player_controls_play"), for: .normal)
+ }
+}
+