//
//  AudioRecordTool.swift
//  LegendTeam
//
//  Created by dong on 2022/1/2.
//

import Foundation
import AVFoundation

@objcMembers class AudioRecordTool: NSObject {
    var timeCount: Int = 0
    var timer: Timer?
    var audioRecorder: AVAudioRecorder?
    var audioURL: URL?

    var audioTmpName: String = ""

    public var timerChangedBlock: ((_ index: Int) -> Void)?
    public var comleteBlock: ((_ path: URL?) -> Void)?

    override init() {
        super.init()
        audioTmpName = generateAudioName()
    }

    @discardableResult
    static func audioAuth(showAlert: Bool = true) -> Bool {
        let authStatus = AVCaptureDevice.authorizationStatus(for: .audio)
        if authStatus == .notDetermined {
            let audioSession = AVAudioSession.sharedInstance()
            audioSession.requestRecordPermission { _ in
                // 这里allowed 为false时，看是否需要弹一个弹窗
            }
            return false
        } else if authStatus == .restricted || authStatus == .denied {
            let alertContent = "Please open the microphone permission in the phone settings"
//            if let existing =  Alert.existingAlertObj() as? Alert, existing.textView.text == alertContent{
//                return false
//            }
            guard showAlert else{
                return false
            }
            let alert = Alert(title: "Notice", text: alertContent)
            let cancelAction = AlertAction(title: "Cancel", actionStyle: .cancel, block: nil)
            let confirmAction = AlertAction(title: "Confirm", actionStyle: .confirm) {
                let url = URL(string: UIApplication.openSettingsURLString)
                if let url = url, UIApplication.shared.canOpenURL(url) {
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                }
            }
            alert.addAction(confirmAction)
            alert.addAction(cancelAction)
            alert.show()
            return false
        } else {
            // 已授权
            return true
        }
    }

    public func startRecord(result: ((_ path: URL?) -> Void)?) {
        timeCount = 0
        clearTimer()

        comleteBlock = result

        do {
            let session = AVAudioSession.sharedInstance()
            try session.setCategory(AVAudioSession.Category.playAndRecord)
            try session.overrideOutputAudioPort(.speaker)
            try session.setActive(true)
            if #available(iOS 13.0, *) {
                try session.setAllowHapticsAndSystemSoundsDuringRecording(true)
            } else {
                // Fallback on earlier versions
            }

            let basePath: String = NSTemporaryDirectory()
            let fileName = generateAudioName()
            audioTmpName = fileName
            let pathComponents = [basePath, fileName]
            audioURL = NSURL.fileURL(withPathComponents: pathComponents)!

            // Create Audiorecorder Object
            audioRecorder = try AVAudioRecorder(url: audioURL!, settings: recordSetting())
            let resultPrepare = audioRecorder!.prepareToRecord()
            dlog("🔥 result:\(resultPrepare)")

            doRecord(fileName: fileName)

        } catch let error as NSError {
            print("! Error coded by developer with 24g45h4qh. Default details: ", error)
        }
    }

    public func stopRecord() {
        CLTool.feedbackGenerator()
        audioRecorder?.stop()
        clearTimer()
        comleteBlock?(audioURL)
    }

    // MARK: - helper

    private func doRecord(fileName: String) {
        if audioRecorder!.isRecording {
            dlog("⚠️已经在录音了")
        } else {
            // start recording
            if let state = audioRecorder?.record(), state == true {
                let myTimer = Timer(timeInterval: 0.1, target: self, selector: #selector(timerDidChanged), userInfo: nil, repeats: true)
                RunLoop.current.add(myTimer, forMode: .common)
                myTimer.fire()
                timer = myTimer
                // call immediately
                timerDidChanged()
            }
        }
    }

    private func clearTimer() {
        if timer != nil {
            timer?.invalidate()
            timer = nil
        }
    }

    private func generateAudioName() -> String {
        let date = Date()
        return "\(date.milliStamp).m4a"
    }

    private func recordSetting() -> [String: AnyObject] {
        var settings: [String: AnyObject] = [:]
        settings[AVFormatIDKey] = Int(kAudioFormatMPEG4AAC) as AnyObject
        settings[AVSampleRateKey] = 44100.0 as AnyObject // 11025, 44100, 22050.0
        settings[AVNumberOfChannelsKey] = 2 as AnyObject
        return settings
    }

    // MARK: - action

    @objc private func timerDidChanged() {
        timeCount += 1
        timerChangedBlock?(timeCount)
        //dlog(timeCount)
    }

    deinit {
        clearTimer()
        CLTool.clearTempFolder()
    }
}
