package com.wdkl.ncs.s433.transbox.utils;

import android.content.Context;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.text.TextUtils;
import android.util.Log;

import com.wdkl.ncs.s433.transbox.common.Constants;

import java.util.ArrayList;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SpeechUtil {
    private static final String TAG = "SpeechUtil";

    private TextToSpeech textToSpeech;
    private static SpeechUtil speech;
    private int loopIndex = 0;
    private int speakIndex = 0;
    private int loopCount = 3;
    private boolean isStop = true;
    public volatile static ArrayList<String> speechTextList = new ArrayList<>();
    private boolean isSpeechLoop = true;
    private String speakSpeech;
    private final Object lockObject = new Object();
    private Bundle params;

    private final ExecutorService threadPool = Executors.newSingleThreadExecutor();
    private SpeechRunnable speechRunnable;
    private PowerManager.WakeLock mWakeLock;

    public static SpeechUtil getInstance() {
        if (speech == null) {
            synchronized (SpeechUtil.class) {
                if (speech == null) {
                    speech = new SpeechUtil();
                }
            }
        }
        return speech;
    }

    public void init(Context context, final TtsCallback callback) {
        final String language = "zh";
        //8.0以下版本自动设置tts
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ) {
            if (Locale.CHINESE.getLanguage().equals(language)) {
                textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
                    @Override
                    public void onInit(int status) {
                        if (status == TextToSpeech.SUCCESS) {
                            int supported = textToSpeech.setLanguage(new Locale(language));
                            if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
                                Constants.TTS_STATUS = 1;
                                Log.d(TAG, "onInit: 当前不支持" + language);
                                if (callback != null) {
                                    callback.onInit(false);
                                }
                            } else {
                                Constants.TTS_STATUS = 2;
                                Log.d(TAG, "onInit: 支持" + language);
                                if (callback != null) {
                                    callback.onInit(true);
                                }
                            }
                            Log.d(TAG, "onInit: TTS引擎初始化成功");
                        } else {
                            Constants.TTS_STATUS = 0;
                            Log.d(TAG, "onInit: TTS引擎初始化失败");
                            if (callback != null) {
                                callback.onInit(false);
                            }
                        }
                    }
                }, "com.iflytek.speechcloud");
            } else {
                textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
                    @Override
                    public void onInit(int status) {
                        if (status == TextToSpeech.SUCCESS) {
                            int supported = textToSpeech.setLanguage(new Locale(language));
                            if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
                                Constants.TTS_STATUS = 1;
                                Log.d(TAG, "onInit: 当前不支持" + language);
                                if (callback != null) {
                                    callback.onInit(false);
                                }
                            } else {
                                Constants.TTS_STATUS = 2;
                                Log.d(TAG, "onInit: 支持" + language);
                                if (callback != null) {
                                    callback.onInit(true);
                                }
                                textToSpeech.setSpeechRate(0.9f);
                            }
                            Log.d(TAG, "onInit: TTS引擎初始化成功");
                        } else {
                            Constants.TTS_STATUS = 0;
                            Log.d(TAG, "onInit: TTS引擎初始化失败");
                            if (callback != null) {
                                callback.onInit(false);
                            }
                        }
                    }
                }, "com.google.android.tts");
            }
        } else {
            //8.0以上版本需要手动设置tts
            textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
                @Override
                public void onInit(int status) {
                    if (status == TextToSpeech.SUCCESS) {
                        int supported = textToSpeech.setLanguage(new Locale(language));
                        if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
                            Constants.TTS_STATUS = 1;
                            Log.d(TAG, "onInit: 当前不支持" + language);
                            if (callback != null) {
                                callback.onInit(false);
                            }
                        } else {
                            Constants.TTS_STATUS = 2;
                            Log.d(TAG, "onInit: 支持" + language);
                            if (callback != null) {
                                callback.onInit(true);
                            }
                            if (!Locale.CHINESE.getLanguage().equals(language)) {
                                textToSpeech.setSpeechRate(0.9f);
                            }
                        }
                        Log.d(TAG, "onInit: TTS引擎初始化成功");
                    } else {
                        Constants.TTS_STATUS = 0;
                        Log.d(TAG, "onInit: TTS引擎初始化失败");
                        if (callback != null) {
                            callback.onInit(false);
                        }
                    }
                }
            });
        }
        //textToSpeech.setSpeechRate(0.5f);

        params = new Bundle();
        params.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_MUSIC);

        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Speech_tag");

        startSpeechThread();
    }

    public void addSpeech(String text, boolean emergency) {
        synchronized (lockObject) {
            Log.d(TAG, "start add text speech: " + text);

            if (speechTextList.contains(text)) {
                return;
            }
            Log.d(TAG, "truely add text speech: " + text);

            if (emergency) {
                stopSpeak();
                speechTextList.add(0, text);
            } else {
                speechTextList.add(text);
            }
            //startSpeechThread();
        }
    }

    public synchronized void speak(final String text) {
        Log.d(TAG, "tts speak: " + text);

        isStop = false;
        textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, params, "uniqueId");
        textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
            @Override
            public void onStart(String utteranceId) {
                //LogUtil.d(TAG, "speak onStart..." + utteranceId);
            }

            @Override
            public void onDone(String utteranceId) {
                speakIndex++;
                //LogUtil.d(TAG, "speak onDone...index: " + speakIndex + ", loop: " + loopCount);
                if (speakIndex < loopCount) {
                    //循环播报
                    speak(text);
                } else {
                    //语音播报完毕
                    speakIndex = 0;
                    isStop = true;
                }
            }

            @Override
            public void onError(String utteranceId) {
                isStop = true;
                Log.d(TAG, "speak onError..." + utteranceId);
            }
        });
    }

    public void stopSpeak() {
        speechTextList.clear();
        if (textToSpeech != null && textToSpeech.isSpeaking()) {
            textToSpeech.stop();
            isStop = true;
            speakIndex = 0;
            loopIndex = 0;

            Log.d(TAG, "stop speak");
        }
    }

    public void removeSpeak(String text) {
        synchronized (lockObject) {
            if (!TextUtils.isEmpty(text) && !TextUtils.isEmpty(speakSpeech)) {
                Log.d(TAG, "remove speak: " + text);

                if (text.equals(speakSpeech) && textToSpeech.isSpeaking()) {
                    textToSpeech.stop();
                    speechTextList.remove(text);
                    isStop = true;
                    speakIndex = 0;
                } else {
                    speechTextList.remove(text);
                }
            }
        }
    }

    public void setSpeechLoopCount(int count) {
        loopCount = count;
    }

    public void release() {
        speechTextList.clear();
        isStop = true;
        speakIndex = 0;
        if (textToSpeech != null) {
            textToSpeech.stop();
            textToSpeech.shutdown();
            textToSpeech = null;
        }
        releaseWakeLock();
    }

    public void startSpeechThread() {
        if (null == speechRunnable) {
            speechRunnable = new SpeechRunnable();
        }

        acquireWakeLock();
        threadPool.execute(speechRunnable);
    }

    public class SpeechRunnable implements Runnable {
        public void run() {
            while (isSpeechLoop) {
                if (speechTextList.size() > 0 && isStop) {
                    /*speakSpeech = speechTextList.get(0);
                    Log.d(TAG, "speakSpeech: " + speakSpeech);
                    speak(speakSpeech);
                    speechTextList.remove(speakSpeech);*/

                    //循环播报
                    if (loopIndex >= speechTextList.size()) {
                        loopIndex = 0;
                    }
                    speakSpeech = speechTextList.get(loopIndex);

                    Log.d(TAG, "speakSpeech: " + speakSpeech + ", speak loopIndex: " + loopIndex + ", speech size: " + speechTextList.size());
                    speak(speakSpeech);

                    loopIndex++;
                }

                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void acquireWakeLock() {
        if (mWakeLock != null) {
            mWakeLock.acquire();
        }
    }

    private void releaseWakeLock() {
        if (mWakeLock != null) {
            mWakeLock.release();
        }
    }


    public interface TtsCallback {
        void onInit(boolean success);
    }
}
