//
//  SHAVAudioManager.swift
//  ShorthandMaster
//
//  Created by 明津李 on 2020/9/27.
//  Copyright © 2020 明津李. All rights reserved.
//

import UIKit
import AVFoundation
import Speech

class SHAVAudioManager: NSObject, SFSpeechRecognizerDelegate {
    
    @objc static let shared = SHAVAudioManager()
    
    private override init() {}
    
    // 创建语音识别器，指定语音识别的语言环境 locale ,将来会转化为什么语言，这里是使用的当前区域，那肯定就是简体汉语啦
//    private let speechRecognizer = SFSpeechRecognizer(locale: Locale.autoupdatingCurrent)
    private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh-CN"))
    // url : 录音文件的路径
    var monitor_file_path = DocumentPath.appending("/monitor.wav")
    
    var session: AVAudioSession {
        let session:AVAudioSession = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker)
        }catch{
            print("session config failed")
        }
        return session
    }

    // 发起语音识别请求，为语音识别器指定一个音频输入源，这里是在音频缓冲器中提供的识别语音。
    private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
    // 语音识别任务，可监控识别进度。通过他可以取消或终止当前的语音识别任务
    private var recognitionTask: SFSpeechRecognitionTask?
    // 语音引擎，负责提供录音输入
    private var audioEngine = AVAudioEngine()
    // 文本数据
    private var recognitionTaskText: [String] = []
    
    lazy var monitor: AVAudioRecorder? = self.getRecorder(monitor_file_path)
    
    private func getRecorder(_ path:String) -> AVAudioRecorder?{
        // setting : 录音的设置项
        // 录音参数设置(不需要掌握, 一些固定的配置)
        let configDic: [String: AnyObject] = [
            // 编码格式
            AVFormatIDKey: NSNumber(value: Int32(kAudioFormatLinearPCM)),
            // 采样率
            AVSampleRateKey: NSNumber(value: 14400.0),
            //采样位数
            AVLinearPCMBitDepthKey: NSNumber(value: 16),
            // 通道数
            AVNumberOfChannelsKey: NSNumber(value: 2),
            // 录音质量
            AVEncoderAudioQualityKey: NSNumber(value: Int32(AVAudioQuality.max.rawValue))
        ]
        do {
            let recorder = try AVAudioRecorder(url: URL(fileURLWithPath: path), settings: configDic)
            recorder.isMeteringEnabled = true
            // 准备录音(系统会给我们分配一些资源)
            recorder.prepareToRecord()
            return recorder
        }catch {
            print(error)
            return nil
        }
    }
    
    private var recorderTimer: SHTimer?
    var resultTxts: [String] = []
    
    private func configRecorder(){

        speechRecognizer?.delegate = self
        AVAudioSession.sharedInstance().requestRecordPermission { (allowed) in
            if !allowed {
                return
             }
        }
        let session:AVAudioSession = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker)
        }catch{
            print("session config failed")
        }

        do { try AVAudioSession.sharedInstance().setActive(true) }
        catch { print("session active failed") }
    }
    
    private func configSpeechTask(){
        
        audioEngine = AVAudioEngine()
        // 初始化RecognitionRequest，在后边我们会用它将录音数据转发给苹果服务器
        recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
        // 在用户说话的同时，将识别结果分批次返回
        recognitionRequest?.shouldReportPartialResults = true
        // 使用recognitionTask方法开始识别。
        recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest!, resultHandler: { (result, error) in
            // 用于检查识别是否结束
            var isFinal = false
            // 如果 result 不是 nil,
            var ss = ""
            if result != nil {

                ss = result?.bestTranscription.formattedString ?? ""
                print("result?.bestTranscription.formattedString ====   \(ss)")

                // 如果 result 是最终，将 isFinal 设置为 true
                isFinal = (result?.isFinal)!
            }
            
            // 如果没有错误发生，或者 result 已经结束，停止audioEngine 录音，终止 recognitionRequest 和 recognitionTask
            if error != nil || isFinal {
                if ss.length > 0 {
                    self.resultTxts.append(ss)
                    print("self.resultTxts ====   \(self.resultTxts)")
                }
            }
        })
        
        // 向recognitionRequest加入一个音频输入
        let recordingFormat = audioEngine.inputNode.outputFormat(forBus: 0)
        audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
            self.recognitionRequest?.append(buffer)
        }
        
        self.audioEngine.prepare()
        
        do {
            // 开始录音
            try audioEngine.start()
        } catch {
            print("audioEngine couldn't start because of an error.")
        }
    }
    
    @objc private func updateMeters() {
        self.monitor?.updateMeters()
        // 获得0声道的音量，完全没有声音-160.0，0是最大音量
        let decibels = (self.monitor?.peakPower(forChannel: 0))!
        print("decibels == \(decibels)")
        if decibels > -24 {
            
        }else{
//            recorderTimer?.invalidate()

//            audioEngine.stop()
//            recognitionRequest = nil
            recognitionTask = nil
            recorderDataSourceHandler()
        }
    }

    func recorderDataSourceHandler(){
//        start()
//        recorderTimer?.invalidate()
//        monitor?.stop()
//        monitor?.deleteRecording()
//        recorder?.stop()
//        recorder?.deleteRecording()
    }
    
    func start(){
        self.configRecorder()
        self.configSpeechTask()
        
//        self.recorder?.record()
        self.monitor?.record()
        
        recorderTimer = SHTimer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateMeters), userInfo: nil, repeats: true)
    }
    
    func pause(){
//        monitor?.stop()
//        monitor?.deleteRecording()
//        recorder?.stop()
//        recorder?.deleteRecording()
    }
    
    func stop(){
//        monitor?.stop()
//        monitor?.deleteRecording()
//        recorder?.stop()
//        recorder?.deleteRecording()
        
        recorderTimer?.invalidate()
    }
}
