package cn.i2edu.speech_plugin.util

import android.content.Context
import android.util.Log
import cn.i2edu.speech_plugin.audioUtils.audiotransfer.DecodeEngine
import cn.i2edu.speech_plugin.audioUtils.audiotransfer.DecodeOperateInterface
import cn.i2edu.speech_plugin.model.chivox.ChivoxResult
import com.alibaba.fastjson.JSON
import com.chivox.AIEngine.*
import java.io.File
import java.io.FileInputStream

interface ChivoxEvaluatorCallBack {
    fun onResult(result: ChivoxResult)
    fun onError(message: String)
}

class ChivoxAudioEvaluatorUtil private constructor(val context: Context) {

    private var chivoxEvaluatorCallBack: ChivoxEvaluatorCallBack? = null
    private var engine: Long? = null
    private val TAG: String = "ChivoxAudioEvaluator"

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

        fun getInstance(context: Context) = instance
                ?: synchronized(this) {
                    instance
                            ?: ChivoxAudioEvaluatorUtil(context)
                                    .also {
                                    }
                                    .also { instance = it }
                }
    }

    fun startEvaluator(en: String, filePath: String, decodedFilePath: String) {
        val provisionPath = AIEngineHelper.extractResourceOnce(context, "aiengine.provision", false)
        val logFilePath = AIEngineHelper.getFilesDir(context).path
        engine = aiengine_new(
                "{\"appKey\": \"157775873600002d\"," +
                        " \"secretKey\": \"a6c766845f9a83974aed16f103e60621\"," +
                        " \"provision\": \"$provisionPath\"," +
                        " \"prof\":{ \"enable\": 0, \"output\": \"$logFilePath/log.txt\"}," +
                        "\"cloud\": {\"server\": \"ws://cloud.chivox.com\"}}", context)

        if (engine == null || engine == 0L) {
            chivoxEvaluatorCallBack?.onError("new aiengine fail")
            return
        } else {
            val param = "{\"coreProvideType\": \"cloud\"," +
                    " \"app\": {\"userId\": \"i2_school_sign\"}," +
                    " \"audio\": {\"audioType\": \"wav\", \"channel\": 1, \"sampleBytes\": 2, \"sampleRate\": 16000}," +
                    " \"request\": {\"coreType\": \"en.sent.score\",\"refText\":\"$en\", \"rank\": 100}}"
            val tokenId = ByteArray(64)
            val callback = aiengine_callback { id, type, data, size ->
                if (type == AIENGINE_MESSAGE_TYPE_JSON) {
                    try {
                        val jsonString = String(data, 0, size).trim { it <= ' ' }
                        Log.d(TAG, jsonString)// 回结果是json格式
                        val result = JSON.parseObject(jsonString, ChivoxResult::class.java) //返回值
                        chivoxEvaluatorCallBack?.onResult(result)
                    } catch (e: java.lang.Exception) {
                        chivoxEvaluatorCallBack?.onError("parse json object failed ${e.message}")
                    }
                }
                onDestory()
                0
            }
            aiengine_start(engine!!, param, tokenId, callback, context)

            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)
                            var byteCount = fileInputStream.read(bytes)
                            while (byteCount > 0) {
                                aiengine_feed(engine!!, bytes, byteCount)
                                Thread.sleep(10)
                                byteCount = fileInputStream.read(bytes)
                            }
                            aiengine_stop(engine!!)
                            file.delete()
                            fileInputStream.close()
                        } catch (e: Exception) {
                            e.printStackTrace()
                            chivoxEvaluatorCallBack?.onError("aiengine_feed failed ${e.message}")
                            onDestory()
                        }
                    }

                    override fun decodeFail() {
                        chivoxEvaluatorCallBack?.onError("decode fail")
                        onDestory()
                    }
                })
            }.start()
        }
    }

    fun setEvaluatorCallBack(callback: ChivoxEvaluatorCallBack): ChivoxAudioEvaluatorUtil? {
        this.chivoxEvaluatorCallBack = callback
        return instance
    }

    fun onDestory() {
        engine?.let {
            aiengine_delete(engine!!)
        }
    }
}