package com.hh.lib_tts.voice;

import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.text.TextUtils;


import com.hh.lib_base.BaseApplication;
import com.hh.lib_base.log.AppLogUtils;

import java.lang.reflect.Field;
import java.util.Locale;

public class MTTSDemo implements TextToSpeech.OnInitListener {


    //用volatile关键字确保 instance 在多线程下的可见性
    private static volatile MTTSDemo instance = null;
    private String speakContent = "";
    float pitch=1.0f;
    float rate=1.0f;
    int speechQueue=1;
    //将构造方法私有化，禁止外部通过构造方法创建实例
    private MTTSDemo() {
    }

    //提供一个公共的访问方法，用于获取该类的唯一实例
    public static MTTSDemo getInstance(Context context) {
        //如果instance为空，就进行实例化
        if (instance == null) {
            //保证多线程下只有一个线程进行实例化
            synchronized (MTTSDemo.class) {
                //第二次判断，避免多线程下创建多个实例
                if (instance == null) {
                    instance = new MTTSDemo(BaseApplication.getContext());
                }
            }
        }
        return instance;
    }


    private TextToSpeech mTTS;


    public MTTSDemo(Context mContext) {
        //监听器就直接传入本类
        this.mTTS = new TextToSpeech(mContext, this);
    }



    public void jump() {
        String enginePackageName = mTTS.getDefaultEngine();


    }

    public void speakStop() {
        mTTS.stop();
    }


    /**
     * 销毁播报方法，直接调用
     */
    public void stopTTS() {
        if (mTTS != null) {
            mTTS.stop();
            mTTS.shutdown();
            mTTS = null;
        }
        instance = null;
    }






    public synchronized void speak(String text, float pitch, float rate, Integer speechQueue) {
        if (TextUtils.isEmpty(text)) {
            AppLogUtils.e(true, "TTS语音播报", "语音内容为空 ");
            return;
        }
        AppLogUtils.e(false, "TTS语音播报", "TTS语音播报内容 ： " + text);
        speakContent = text;
        this.pitch=pitch;
        this.rate=rate;
        this.speechQueue=speechQueue;
        //设置音调，值越大声音越尖（女生），值越小则变成男声，1.0是常规
        mTTS.setPitch(pitch);
        //设置语速
        mTTS.setSpeechRate(rate);


        // 设置播报队列方式
        if(speechQueue == null){
            speechQueue = 0;
        }
        int mTTsState = TextToSpeech.ERROR;
        if (speechQueue == 0) {
            // TextToSpeech.QUEUE_ADD添加到队列后面,依次将前面的读完轮序
            mTTsState = mTTS.speak(text, TextToSpeech.QUEUE_ADD, null,"hharome");
        }else if(speechQueue == 1) {
            // TextToSpeech.QUEUE_FLUSH刷新队列,将之前的队列取消阅读现在的文字
            mTTsState = mTTS.speak(text, TextToSpeech.QUEUE_FLUSH, null,"hharome");
        }
        if(mTTsState != TextToSpeech.SUCCESS){
            reset(text,speechQueue);
        }
    }

    private void reset(String text,final int speechQueue){
        if (mTTS != null){
            mTTS.stop();
            mTTS.shutdown();
        }
        mTTS = new TextToSpeech(BaseApplication.getContext(), status -> {
            if (status == TextToSpeech.SUCCESS) {
                int result = mTTS.setLanguage(Locale.CHINA);
                if (result != TextToSpeech.LANG_COUNTRY_AVAILABLE
                        && result != TextToSpeech.LANG_AVAILABLE) {
                    AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: 不支持这种语言");
                }

                if (0 == speechQueue) {
                    // TextToSpeech.QUEUE_ADD添加到队列后面,依次将前面的读完轮序
                  mTTS.speak(text, TextToSpeech.QUEUE_ADD, null,"hharome");
                }else if(speechQueue == 1) {
                    // TextToSpeech.QUEUE_FLUSH刷新队列,将之前的队列取消阅读现在的文字
                     mTTS.speak(text, TextToSpeech.QUEUE_FLUSH, null,"hharome");
                }
            } else {
                AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: TTS初始化失败");
            }
        }, "com.iflytek.speechcloud");//科大讯飞语音引擎
    }

    @Override
    public void onInit(int status) {
        if (mTTS == null) {
            return;
        }
        //判断是否转化成功
        if (status == TextToSpeech.SUCCESS) {
            //设置语言为中文
            int languageCode = mTTS.setLanguage(Locale.CHINESE);
            //判断是否支持这种语言，Android原生不支持中文，使用科大讯飞的tts引擎就可以了
            if (languageCode == TextToSpeech.LANG_NOT_SUPPORTED) {
                AppLogUtils.e(true, " TTS - onInit", "TTS语音播报 onInit: 不支持这种语言");
            } else {
                //不支持就改成英文
                mTTS.setLanguage(Locale.US);
            }
            int mTTsState = TextToSpeech.ERROR;
            mTTsState = mTTS.speak("", TextToSpeech.QUEUE_FLUSH, null,"hharome");
            if(mTTsState != TextToSpeech.SUCCESS){
                reset("",speechQueue);
            }

        } else {
            // 检查语音数据是否已下载
            if (mTTS.isLanguageAvailable(Locale.CHINESE) >= TextToSpeech.LANG_AVAILABLE) {
                AppLogUtils.e(false, "TTS - onInit", "-----------speakContent " + speakContent);
                speak(speakContent,pitch,rate,speechQueue);
            } else {
                AppLogUtils.e(false, " TTS - onInit", "中文语音数据未完整下载。");
            }
        }
    }


    /**
     * TTS初始化之后有时会无法播放语音。
     * 从打印日志看failed: not bound to TTS engine
     * 找到源代码打印处
     * if (mServiceConnection == null) {
     * Log.w(TAG, method + " failed: not bound to TTS engine");
     * return errorResult;
     * }
     * 通过反射判断mServiceConnection是否为空
     *
     * @param tts
     * @return true 可用
     */
    public static boolean ismServiceConnectionUsable(TextToSpeech tts) {

        boolean isBindConnection = true;
        if (tts == null) {
            return false;
        }
        Field[] fields = tts.getClass().getDeclaredFields();
        for (int j = 0; j < fields.length; j++) {
            fields[j].setAccessible(true);
            if (TextUtils.equals("mConnectingServiceConnection", fields[j].getName()) && TextUtils.equals("android.speech.tts.TextToSpeech$Connection", fields[j].getType().getName())) {
                try {
                    if (fields[j].get(tts) == null) {
                        isBindConnection = false;
                    }
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return isBindConnection;
    }
}
