//
//  BFAudioPlayer.swift
//  PQSpeed
//
//  Created by ak on 2020/8/14.
//  Copyright © 2020 BytesFlow. All rights reserved.
//  功能：播放音频文件
/*  e.g.
 
 BFAudioPlayer.shared.configPlayer(audioPathURL: audioPath)
 BFAudioPlayer.shared.delegate = self
 BFAudioPlayer.shared.playOrPause()
 */

import Foundation

import AVFoundation
import UIKit

@objc protocol BFAudioPlayerDelegate: NSObjectProtocol {
    // 播放完成
    @objc optional func audioPlayerDidFinish()

    // 播放开始
    @objc optional func audioPlayerStart()
    // 播放进度
    @objc optional func playProgress(currentTime: TimeInterval, progress: Double)
}

class BFAudioPlayer: NSObject {
    // MARK: - Variables

    var player: AVAudioPlayer?
    var title: String = ""
    var artist: String = ""
    var album: String = ""
    var artwork: UIImage?

    private var timer: Timer?

    weak var delegate: BFAudioPlayerDelegate?

    // MARK: - Constructor

    override func copy() -> Any {
        return self
    }

    override func mutableCopy() -> Any {
        return self
    }

    static let shared = BFAudioPlayer()

    override private init() {
        super.init()
    }

    func configPlayer(audioPathURL: URL) {
        BFLog(message: "audioPath is \(audioPathURL.relativePath)")
        loadMetaDataFromAudioFile(audioPathURL)
        if !(player != nil && player?.url?.absoluteString == audioPathURL.absoluteString) {
            do {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
                try AVAudioSession.sharedInstance().setActive(true)

                // Prepare player
                let data: Data = try Data(contentsOf: audioPathURL)
                player = try AVAudioPlayer(data: data)

            } catch _ {
                BFLog(message: "播放失败 向上看 系统LOG ")
                return
            }
            player?.currentTime = 0
            player?.delegate = self
            player?.enableRate = true
            player?.prepareToPlay()
        }
    }

    // MARK: - Internal methods

    func playOrPause() {
        if player?.isPlaying ?? false {
            stopTimer()
            player?.pause()
            BFLog(message: "停止播放了")
        } else {
            if delegate != nil {
                delegate?.audioPlayerStart!()
            }
            startTimer()
            player?.play()
            BFLog(message: "playOrPause开始播放了")
        }
    }

    func pause() {
        if player != nil, player?.isPlaying ?? false {
            BFLog(message: "停止播放了")
            stopTimer()
            player?.pause()
        }
    }

    func play() {
        if delegate != nil {
            delegate?.audioPlayerStart!()
        }
        BFLog(message: "开始播放了")
        player?.play()
        startTimer()
    }

    func stop() {
        stopTimer()
        if player != nil {
            player?.stop()
        }
    }

    func setRate(_ rate: Float) {
        player?.rate = rate
    }

    func setPlayingTime(_ pos: Double) {
        player?.currentTime = pos
    }

    // MARK: - Private methods

    func loadMetaDataFromAudioFile(_ url: URL) {
        let asset: AVAsset = AVURLAsset(url: url, options: avAssertOptions)
        let metadata: Array = asset.commonMetadata

        for item in metadata {
            switch item.commonKey {
            case AVMetadataKey.commonKeyTitle:
                title = item.stringValue!
            case AVMetadataKey.commonKeyAlbumName:
                album = item.stringValue!
            case AVMetadataKey.commonKeyArtist:
                artist = item.stringValue!
            case AVMetadataKey.commonKeyArtwork:
                artwork = UIImage(data: item.dataValue!)
            default:
                break
            }
        }
    }

    // 开始计时
    func startTimer() {
        if timer == nil {
            timer = PQWeakTimer.scheduledTimer(timeInterval: 1 / 60, target: self, repeats: true) { [weak self] _ in

//                BFLog(message: "播放进度 \(String(describing: self?.player?.currentTime)) 总时长：\(String(describing: self?.player?.duration))")
                // currentTime 有可能不是从0开始
                var progress = 0.0
                if self?.player?.duration ?? 0 > 0 {
                    progress = Double((self?.player?.currentTime ?? 0) / (self?.player?.duration ?? 1))
                }
//                BFLog(message: "progress is \(progress) currentTime\(self?.player?.currentTime)")
                if self?.delegate != nil {
                    self!.delegate!.playProgress!(currentTime: self?.player?.currentTime ?? 0, progress: progress)
                }
            }
        }
    }

    // 停止计时
    func stopTimer() {
        if timer != nil {
            timer?.invalidate() // 销毁timer
            timer = nil
        }
    }
}

extension BFAudioPlayer: AVAudioPlayerDelegate {
    func audioPlayerDidFinishPlaying(_: AVAudioPlayer, successfully _: Bool) {
        if delegate != nil {
            delegate?.audioPlayerDidFinish!()
        }
        stop()

        // Send notification
        let notification = Notification(name: Notification.Name(rawValue: "stop"), object: self)
        NotificationCenter.default.post(notification)
    }
}
