package com.xty.common.audioUtils

import android.content.Context
import android.media.*
import com.xty.common.FileUtils
import com.xty.common.LogUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import java.io.*


class RecordAudio {
    var player: MediaPlayer? = null// 播放
    var isPause: Boolean = false//是否被中断过

    var isRecording = false

    init {
        player = MediaPlayer()
    }

    /**
     * 音频播放的回调
     */
    interface AudioPlayStateListener {
        //开始
        fun onStart()

        //完成
        fun onComplet()

        //加载异常
        fun onError()
    }


    /**
     * 音频播放
     */
    fun audioPlay(url: String, audioPlayStateListener: AudioPlayStateListener? = null) {
        player?.let {
            audioPlayStateListener?.onStart()

            stopPlay()//如果语音正在播放则停止,会调用reset方法。因为在setDataSource之前，不管怎样都要reset一次，不然会报IllegalStateException

            //播放完毕事件监听
            it.setOnCompletionListener { it1 ->
                LogUtils.d("播放完毕 ")
                stopPlay()
                audioPlayStateListener?.onComplet()
            }

            //监听媒体流是否装载完成
            it.setOnPreparedListener {
                Thread {
                    it.start()
                }.start()
            }

            //监听流媒体加载出错的问题
            it.setOnErrorListener { mediaPlayer, what, extra ->
                LogUtils.e("加载文件错误 url:$url what:$what extra:$extra")
                stopPlay()
                audioPlayStateListener?.onError()
                true
            }

            it.setDataSource(url)
            it.setAudioStreamType(AudioManager.STREAM_MUSIC)
            it.prepareAsync()
        }
    }

    /**
     * 播放完毕
     */
    fun stopPlay() {
        player?.let {
            if(player != null && it.isPlaying){
                it.stop()
            }
            it.reset()
        }

    }

    /**
     * 如果 播放时间过长,如30秒
     * 用户突然来电话了,则需要暂停
     */
    fun pause() {
        if (player != null && player!!.isPlaying) {
            isPause = true
            player!!.pause()
        }
    }

    /**
     * 播放
     */
    fun resume() {
        if (player != null && isPause) {
            isPause = false
            player!!.start()
        }
    }

    /**
     * activity 被销毁  释放
     */
    fun release() {
        if (player != null) {
            player!!.stop()
            player!!.release()
            player = null
        }
    }

    /**
     * 录制pcm文件的音频
     * 这个属于音频源文件一般播放器无发播放  需要使用ffplay进行格式转换
     */
    fun startRecord(context: Context) {
        var recordingFile: File
        //AudioRecord不会直接保存音频。须要自己保存
        val path = FileUtils.getCacheFile(context) + File.separator + "audio"
        var file = File(path)
        if (!file.exists()) {
            file.mkdirs()
        }

        try {
            var name = "${System.currentTimeMillis()}_audio"
            recordingFile = File.createTempFile(name, ".pcm", file)
            MainScope().launch(Dispatchers.IO) {
                var dos = DataOutputStream(BufferedOutputStream(FileOutputStream(recordingFile)))
                val bufferSize: Int =
                    AudioRecord.getMinBufferSize(
                        44100,
                        AudioFormat.CHANNEL_IN_MONO,
                        AudioFormat.ENCODING_PCM_16BIT
                    )
                val audioRecord =
                    AudioRecord(
                        MediaRecorder.AudioSource.MIC,
                        44100,
                        AudioFormat.CHANNEL_IN_MONO,
                        AudioFormat.ENCODING_PCM_16BIT,
                        bufferSize
                    )
                val buffer = ShortArray(bufferSize)
                audioRecord.startRecording()
                var r = 0
                while (isRecording) {
                    val bufferReadResult: Int = audioRecord.read(buffer, 0, bufferSize)
                    for (i in 0 until bufferReadResult) {
                        try {
                            dos.writeShort(buffer[i].toInt())
                        } catch (e: IOException) {
                            e.printStackTrace()
                        }
                    }
                    r++
                }
                audioRecord.stop()
                dos.close()

            }
        } catch (e: IOException) {
            e.printStackTrace()
        }

    }
}