package com.dlc.exam.iflytek

import android.content.Context
import android.os.Bundle
import android.os.Environment
import com.iflytek.cloud.*
import com.iflytek.cloud.util.ResourceUtil
import com.rc.core.log.RcLog

/**
 * info
 *
 * @author ReiChin_
 */
object VoiceItsManager {

    // 引擎类型
    private const val mEngineType = SpeechConstant.TYPE_LOCAL

    // 默认云端发音人
    private const val voicerCloud = "xiaoyan"
    private const val voicerLocal = "xiaoyan"

    // 默认本地发音人
    private const val voicerXtts = "xiaoyan"

    // 语音合成对象
    private var mTts: SpeechSynthesizer? = null

    fun initIts(context: Context) {
        release()
        // 初始化合成对象
        mTts = SpeechSynthesizer.createSynthesizer(context, mInitListener)
        setItsParam(context)
    }

    fun release() {
        mTts?.let {
            it.destroy()
            mTts = null
        }
    }

    /*
     * 参数设置
     */
    private fun setItsParam(context: Context) {
        mTts?.apply {
            // 清空参数
            setParameter(SpeechConstant.PARAMS, null)
            // 设置合成
            if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
                // 设置使用云端引擎
                setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD)
                // 设置发音人
                setParameter(SpeechConstant.VOICE_NAME, voicerCloud)
            } else if (mEngineType.equals(SpeechConstant.TYPE_LOCAL)) {
                // 设置使用本地引擎
                setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL)
                // 设置发音人资源路径
                setParameter(ResourceUtil.TTS_RES_PATH, getResourcePath(context))
                // 设置发音人
                setParameter(SpeechConstant.VOICE_NAME, voicerLocal)
            }
            // 设置合成语速
            setParameter(SpeechConstant.SPEED, "50")
            //设置合成音调
            setParameter(SpeechConstant.PITCH, "50")
            //设置合成音量
            setParameter(SpeechConstant.VOLUME, "50")
            //设置播放器音频流类型
            setParameter(SpeechConstant.STREAM_TYPE, "3")
            //	setParameter(SpeechConstant.STREAM_TYPE, AudioManager.STREAM_MUSIC+"")

            // 设置播放合成音频打断音乐播放，默认为true
            setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true")

            // 设置音频保存路径，保存音频格式支持pcm、wav，设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
            setParameter(SpeechConstant.AUDIO_FORMAT, "wav")

            setParameter(
                SpeechConstant.TTS_AUDIO_PATH,
                Environment.getExternalStorageDirectory().path + "/msc/tts.wav"
            )
        }
    }

    fun speakVoice(voiceStr: String, listener: SynthesizerListener = mTtsListener) {
        mTts?.let {
            val code = it.startSpeaking(voiceStr, listener)
            if (code != ErrorCode.SUCCESS) {
                RcLog.info("[Iflytek]语音合成失败,错误码: $code")
            }
        }
    }

    fun speakVoice2(voiceStr: String, listener: ((success: Boolean, errMsg: String?) -> Unit)? = null) {
        mTts?.let {
            val code = it.startSpeaking(voiceStr, object : SimpleSynthesizerListener() {
                override fun onCompleted(error: SpeechError?) {
                    val message = error?.toString()
                    listener?.invoke(null == error, message)
                }
            })
            if (code != ErrorCode.SUCCESS) {
                RcLog.info("[Iflytek]语音合成失败,错误码: $code")
                listener?.invoke(false, "语音合成失败,错误码: $code")
            }
        }
        if (null == mTts) {
            listener?.invoke(false, "mTts == null")
        }
    }

    fun stopVoice() {
        mTts?.let {
            if (it.isSpeaking) it.stopSpeaking()
        }
    }

    // 获取发音人资源路径
    private fun getResourcePath(context: Context): String {
        return StringBuffer().apply {
            val type = "tts"
            // 合成通用资源
            append(
                ResourceUtil.generateResourcePath(
                    context,
                    ResourceUtil.RESOURCE_TYPE.assets,
                    type + "/common.jet"
                )
            )
            append(";")
            // 发音人资源
            append(
                ResourceUtil.generateResourcePath(
                    context,
                    ResourceUtil.RESOURCE_TYPE.assets,
                    type + "/" + voicerLocal + ".jet"
                )
            )
        }.toString()
    }

    /**
     * 初始化监听。
     */
    private val mInitListener = InitListener { code ->
        RcLog.info("[Iflytek] InitListener init() code = $code")
        if (code != ErrorCode.SUCCESS) {
            RcLog.info("[Iflytek]初始化语音合成失败")
        } else {
            // 初始化成功，之后可以调用startSpeaking方法
            // 注：有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成，
            // 正确的做法是将onCreate中的startSpeaking调用移至这里
        }
    }

    /**
     * 合成回调监听。
     */
    private val mTtsListener = object : SynthesizerListener {

        override fun onSpeakBegin() {
            RcLog.info("[Iflytek]开始播放：${System.currentTimeMillis()}")
        }

        override fun onSpeakPaused() {
            RcLog.info("[Iflytek]暂停播放")
        }

        override fun onSpeakResumed() {
            RcLog.info("[Iflytek]继续播放")
        }

        override fun onBufferProgress(percent: Int, beginPos: Int, endPos: Int, info: String?) {
            // 合成进度
            /*mPercentForBuffering = percent;
            showTip(String.format(getString(R.string.tts_toast_format),
                    mPercentForBuffering, mPercentForPlaying));*/
        }

        override fun onSpeakProgress(percent: Int, beginPos: Int, endPos: Int) {
            // 播放进度
            /*mPercentForPlaying = percent;
            showTip(String.format(getString(R.string.tts_toast_format),
                    mPercentForBuffering, mPercentForPlaying));*/
        }

        override fun onCompleted(error: SpeechError?) {
            if (error == null) {
                RcLog.info("[Iflytek]播放完成")
            } else {
                RcLog.info("[Iflytek]播放错误：${error.getPlainDescription(true)}")
            }
        }

        override fun onEvent(eventType: Int, arg1: Int, arg2: Int, obj: Bundle?) {
            // 以下代码用于获取与云端的会话id，当业务出错时将会话id提供给技术支持人员，可用于查询会话日志，定位出错原因
            // 若使用本地能力，会话id为null
            if (SpeechEvent.EVENT_SESSION_ID == eventType) {
                RcLog.info("[Iflytek]onEvent sid=${obj?.getString(SpeechEvent.KEY_EVENT_AUDIO_URL)}")
            }

            //实时音频流输出参考
            /*if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {
                byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);
                Log.e("MscSpeechLog", "buf is =" + buf);
            }*/
        }
    }

    open class SimpleSynthesizerListener : SynthesizerListener {
        /**
         * 开始播放
         */
        override fun onSpeakBegin() {
        }

        /**
         * 合成进度
         */
        override fun onBufferProgress(percent: Int, beginPos: Int, endPos: Int, info: String?) {
        }

        /**
         * 暂停播放
         */
        override fun onSpeakPaused() {
        }

        /**
         * 继续播放
         */
        override fun onSpeakResumed() {
        }

        /**
         * 播放进度
         */
        override fun onSpeakProgress(percent: Int, beginPos: Int, endPos: Int) {
        }

        /**
         * 播放完成
         */
        override fun onCompleted(error: SpeechError?) {
        }

        override fun onEvent(eventType: Int, arg1: Int, arg2: Int, obj: Bundle?) {
        }
    }

}