//
//  SoundPlayer.swift
//  LeCountdown
//
//  Created by Laurent Morvillier on 30/01/2023.
//

import Foundation
import AVFoundation

struct SoundFile {
    
    var filename: String
    var fileExtension: String
    
    init(fullName: String) throws {
        let components = fullName.components(separatedBy: ".")
        if components.count == 2 {
            self.filename = components[0]
            self.fileExtension = components[1]
        } else {
            throw SoundPlayerError.badFileName(name: fullName)
        }
    }
    
    var url: URL? {
        return Bundle.main.url(forResource: self.filename, withExtension: self.fileExtension)
    }
}

enum SoundPlayerError : Error {
    case missingResourceError(file: SoundFile)
    case badFileName(name: String)
}

@objc class SoundPlayer: NSObject, AVAudioPlayerDelegate {
    
    fileprivate var _player: AVAudioPlayer?

    fileprivate var _timer: Timer? = nil
    
    func play(soundFile: SoundFile, for duration: TimeInterval) throws {
        try self.playSound(soundFile: soundFile)
        self._timer = Timer(timeInterval: duration, repeats: false, block: { _ in
            self._player?.stop()
        })
    }
    
    func playSound(soundFile: SoundFile) throws {
        guard let url = soundFile.url else {
            throw SoundPlayerError.missingResourceError(file: soundFile)
        }
        
        let audioSession: AVAudioSession = AVAudioSession.sharedInstance()
        try audioSession.setCategory(.playback)
        try audioSession.setActive(true)

        _player = try AVAudioPlayer(contentsOf: url)
        _player?.prepareToPlay()
        _player?.volume = 1.0
        _player?.delegate = self

        Logger.log("Plays \(url) on player: \(String(describing: self._player))")
        _player?.play()
        
    }
    
    func stop() {
        self._player?.stop()
    }
    
    // MARK: - Delegate
    
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        Conductor.maestro.deactivateAudioSessionIfPossible()
    }
    
}
