package cn.i2edu.speech_plugin.util

import android.content.Context
import android.os.Bundle
import android.util.Log
import cn.i2edu.speech_plugin.audioUtils.audiotransfer.DecodeEngine
import cn.i2edu.speech_plugin.audioUtils.audiotransfer.DecodeOperateInterface
import com.iflytek.cloud.*
import java.io.File
import java.io.FileInputStream

interface IFlyEvaluatorCallBack {
    fun onResult(result: EvaluatorResult)
    fun onError(error: SpeechError)
}

class IFlyAudioEvaluatorUtil private constructor(val context: Context) {

    private var iFlyEvaluatorCallBack: IFlyEvaluatorCallBack? = null
    private var speechEvaluator: SpeechEvaluator? = null
    private val Tag: String = "AudioEvaluatorUtil"

    companion object {
        @Volatile
        private var instance: IFlyAudioEvaluatorUtil? = null

        fun getInstance(context: Context) = instance
                ?: synchronized(this) {
                    instance
                            ?: IFlyAudioEvaluatorUtil(context)
                                    .also {
                                        it.speechEvaluator = SpeechEvaluator.createEvaluator(context, null)
                                    }
                                    .also { instance = it }
                }
    }

    fun startEvaluator(en: String, filePath: String, decodedFilePath: String, evaluatorType: Int) {
        speechEvaluator?.setParameter(SpeechConstant.LANGUAGE, "en_us")
        speechEvaluator?.setParameter(SpeechConstant.ISE_CATEGORY, "read_sentence")
        speechEvaluator?.setParameter(SpeechConstant.AUDIO_SOURCE, "-1")
        if (evaluatorType == 1) {
            speechEvaluator?.setParameter("plev", "0")
        }

        if (!File(decodedFilePath).exists()) {
            File(decodedFilePath).createNewFile()
        }
        Thread {
            DecodeEngine.getInstance(context).beginDecodeMusicFile(filePath, decodedFilePath, 0, 16000, 1, 2, object : DecodeOperateInterface {
                override fun updateDecodeProgress(decodeProgress: Int) {
                }

                override fun decodeSuccess() {
                    try {
                        val file = File(decodedFilePath)
                        val fileInputStream = FileInputStream(file)
                        val bytes = ByteArray(1024)
                        speechEvaluator?.startEvaluating(en, null, object : EvaluatorListener {
                            override fun onVolumeChanged(p0: Int, p1: ByteArray?) {
                            }

                            override fun onResult(p0: EvaluatorResult, p1: Boolean) {
                                Log.d(Tag, p0.toString())
                                iFlyEvaluatorCallBack?.onResult(p0)
                                file.delete()
                                onDestory()
                            }

                            override fun onBeginOfSpeech() {
                            }

                            override fun onEvent(p0: Int, p1: Int, p2: Int, p3: Bundle?) {
                            }

                            override fun onEndOfSpeech() {
                            }

                            override fun onError(p0: SpeechError) {
                                Log.d(Tag, p0.toString())
                                iFlyEvaluatorCallBack?.onError(p0)
                                file.delete()
                                onDestory()
                            }
                        })
                        var byteCount = fileInputStream.read(bytes)
                        while (byteCount > 0) {
                            speechEvaluator?.writeAudio(bytes, 0, byteCount)
                            Thread.sleep(10)
                            byteCount = fileInputStream.read(bytes)
                        }
                        speechEvaluator?.stopEvaluating()
                        fileInputStream.close()
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }

                }

                override fun decodeFail() {
                    val speechError = SpeechError(1, "评测失败，请稍后再试！")
                    iFlyEvaluatorCallBack?.onError(speechError)
                }
            })
        }.start()
    }

    fun setEvaluatorCallBack(callBackIFly: IFlyEvaluatorCallBack): IFlyAudioEvaluatorUtil? {
        this.iFlyEvaluatorCallBack = callBackIFly
        return instance
    }

    fun onDestory() {
        speechEvaluator?.destroy()
    }
}