/*
 * 语音识别辅助类 - 基于讯飞语音SDK
 */
package net.micode.notes.tool;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.Log;

import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

public class VoiceRecognizer {
    private static final String TAG = "VoiceRecognizer";
     private static final String APP_ID = "be812aa3"; // 替换为实际的讯飞应用ID

// 

    private Context mContext;
    private SpeechRecognizer mIat;
    private OnRecognitionListener mListener;
    private StringBuilder mResult = new StringBuilder();
    private Handler mHandler = new Handler();
    private int mRetryCount = 0;
    private static final int MAX_RETRY_COUNT = 3;
    private Vibrator mVibrator;
    private boolean mIsRecording = false; // 是否正在录音（按住状态）

    public interface OnRecognitionListener {
        void onResult(String result);
        void onError(int code, String message);
    }

    public VoiceRecognizer(Context context) {
        mContext = context;
        // 获取振动器服务
        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        // 初始化SDK
        SpeechUtility.createUtility(context, SpeechConstant.APPID + "=" + APP_ID);
        // 延迟初始化，避免启动问题
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                initRecognizer();
            }
        }, 500);
    }

    private void initRecognizer() {
        // 创建识别器
        mIat = SpeechRecognizer.createRecognizer(mContext, new InitListener() {
            @Override
            public void onInit(int code) {
                if (code != ErrorCode.SUCCESS) {
                    Log.e(TAG, "初始化失败，错误码：" + code);
                } else {
                    Log.d(TAG, "初始化成功");
                }
            }
        });

        // 设置识别参数
        setRecognizerParam();
    }

    private void setRecognizerParam() {
        if (mIat == null) {
            return;
        }

        // 清除所有参数
        mIat.setParameter(SpeechConstant.PARAMS, null);

        // 设置中文普通话
        mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        mIat.setParameter(SpeechConstant.ACCENT, "mandarin");

        // 设置采样率
        mIat.setParameter(SpeechConstant.SAMPLE_RATE, "16000");

        // 设置引擎类型为云端
        mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);

        // 设置为长按模式
        mIat.setParameter(SpeechConstant.ASR_PTT, "1"); // 1表示长按模式
        
        try {
            // 使用麦克风作为音频源
            mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "1"); // 1表示使用麦克风
            
            // 调整VAD参数 - VAD_BOS是语音前端点检测，VAD_EOS是语音后端点检测
            mIat.setParameter(SpeechConstant.VAD_BOS, "4000"); // 语音前端点检测：4秒内用户需要开始说话
            mIat.setParameter(SpeechConstant.VAD_EOS, "2000"); // 语音后端点检测：静音2秒后结束
            
            // 设置语音超时时间
            mIat.setParameter(SpeechConstant.KEY_SPEECH_TIMEOUT, "60000"); // 语音超时时间为60秒
            
            // 启用语音活动检测
            mIat.setParameter(SpeechConstant.VAD_ENABLE, "1"); // 开启VAD功能
            
            // 调低语音检测的门限值，使其更容易检测到语音
            mIat.setParameter("vad_threshold", "0"); // 降低检测门限到最低值
            
            // 设置识别结果是否包含标点符号
            mIat.setParameter(SpeechConstant.ASR_PTT, "1"); // 1表示添加标点符号
            
            // 不保存音频
            mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, null);
            
        } catch (Exception e) {
            Log.e(TAG, "设置参数异常", e);
        }
    }

    public void setListener(OnRecognitionListener listener) {
        mListener = listener;
    }

    /**
     * 按下按钮时调用，开始录音但不识别
     */
    public void startRecording() {
        if (mIsRecording) {
            return; // 如果已经在录音中，不再重复开始
        }
        
        mIsRecording = true;
        mResult.setLength(0);
        mRetryCount = 0;
        
        // 开始录音时短振动反馈 (50ms)
        if (mVibrator != null) {
            mVibrator.vibrate(50);
        }
        
        // 确保录音参数正确设置
        if (mIat == null) {
            initRecognizer();
        }
        
        // 设置为仅录音模式，不做语音识别
        try {
            setRecognizerParam();
            // 关键：设置为仅录音模式
            mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, mContext.getCacheDir().getAbsolutePath() + "/temp_record.pcm");
            
            int ret = mIat.startListening(mRecognizerListener);
            if (ret != ErrorCode.SUCCESS) {
                Log.e(TAG, "启动录音失败，错误码：" + ret);
                if (mListener != null) {
                    mListener.onError(ret, "启动录音失败，请检查麦克风权限");
                }
                mIsRecording = false;
            } else {
                Log.d(TAG, "开始录音成功 - 等待松开按钮进行识别");
            }
        } catch (Exception e) {
            Log.e(TAG, "启动录音异常", e);
            if (mListener != null) {
                mListener.onError(-1, "启动录音异常: " + e.getMessage());
            }
            mIsRecording = false;
        }
    }
    
    /**
     * 松开按钮时调用，停止录音并开始识别
     */
    public void stopRecordingAndRecognize() {
        if (!mIsRecording) {
            return; // 如果没有在录音，不处理
        }
        
        // 先标记为非录音状态
        mIsRecording = false;
        
        // 结束录音时短振动反馈 (30ms)
        if (mVibrator != null) {
            mVibrator.vibrate(30);
        }
        
        // 只有在录音状态才执行停止
        if (mIat != null && mIat.isListening()) {
            try {
                // 在这里停止录音并启动识别
                mIat.stopListening();
                Log.d(TAG, "录音已停止，正在进行语音识别");
            } catch (Exception e) {
                Log.e(TAG, "停止录音异常", e);
                if (mListener != null) {
                    mListener.onError(-1, "停止录音异常: " + e.getMessage());
                }
            }
        } else {
            Log.w(TAG, "停止录音时发现语音识别器不在工作状态");
            if (mListener != null) {
                mListener.onError(-1, "录音异常：未检测到正在进行的录音");
            }
        }
    }

    /**
     * 取消识别（用于用户主动取消）
     */
    public void cancelRecognition() {
        mIsRecording = false;
        
        if (mIat != null) {
            try {
                mIat.cancel(); // 取消识别
                Log.d(TAG, "取消识别");
            } catch (Exception e) {
                Log.e(TAG, "取消识别异常", e);
            }
        }
    }
    
    private void startListening() {
        if (mIat == null) {
            Log.d(TAG, "语音识别器未初始化，尝试重新初始化");
            initRecognizer();
            if (mIat == null) {
                if (mListener != null) {
                    mListener.onError(-1, "语音识别器初始化失败");
                }
                return;
            }
        }
        
        if (mIat.isListening()) {
            Log.d(TAG, "语音识别器正在运行中，先停止");
            try {
                mIat.cancel();
                // 短暂延迟后再启动
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        startListeningInternal();
                    }
                }, 300);
            } catch (Exception e) {
                Log.e(TAG, "停止识别失败", e);
                startListeningInternal();
            }
            return;
        }
        
        startListeningInternal();
    }
    
    private void startListeningInternal() {
        // 重置参数
        setRecognizerParam();
        
        try {
            int ret = mIat.startListening(mRecognizerListener);
            if (ret != ErrorCode.SUCCESS) {
                handleStartError(ret);
            } else {
                Log.d(TAG, "启动语音录音成功");
            }
        } catch (Exception e) {
            Log.e(TAG, "启动语音录音异常", e);
            if (mListener != null) {
                mListener.onError(-1, "启动语音录音出现异常: " + e.getMessage());
            }
        }
    }
    
    private void handleStartError(final int errorCode) {
        Log.e(TAG, "启动语音识别失败，错误码：" + errorCode);
        
        if (errorCode == 20006) { // 启动录音失败
            if (mRetryCount < MAX_RETRY_COUNT) {
                mRetryCount++;
                Log.d(TAG, "尝试重试，次数: " + mRetryCount);
                
                // 尝试释放资源后重新初始化
                destroy();
                
                // 延迟重试
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Log.d(TAG, "重新初始化识别器");
                        initRecognizer();
                        startListening();
                    }
                }, 1000);
                return;
            }
        }
        
        // 达到最大重试次数或其他错误码
        if (mListener != null) {
            mListener.onError(errorCode, "语音识别启动失败，错误码：" + errorCode + 
                   (errorCode == 20006 ? "（启动录音失败）" : ""));
        }
    }
    
    // 以下两个方法保留用于兼容现有代码，但内部实现改为新的逻辑
    public void startRecognizing() {
        startRecording();
    }
    
    public void stopRecognizing() {
        stopRecordingAndRecognize();
    }
    
    public void destroy() {
        mIsRecording = false;
        if (mIat != null) {
            try {
                mIat.cancel();
                mIat.destroy();
                Log.d(TAG, "销毁语音识别器");
            } catch (Exception e) {
                Log.e(TAG, "销毁语音识别器异常", e);
            } finally {
                mIat = null;
            }
        }
    }
    
    private RecognizerListener mRecognizerListener = new RecognizerListener() {
        @Override
        public void onVolumeChanged(int volume, byte[] data) {
            // 音量回调，可用于显示音量大小
            Log.d(TAG, "音量大小: " + volume);
        }
        
        @Override
        public void onBeginOfSpeech() {
            // 开始说话的回调
            Log.d(TAG, "开始说话");
        }
        
        @Override
        public void onEndOfSpeech() {
            // 结束说话的回调
            Log.d(TAG, "结束说话");
        }
        
        @Override
        public void onResult(RecognizerResult result, boolean isLast) {
            if (result != null) {
                String text = parseResult(result.getResultString());
                Log.d(TAG, "识别结果: " + text);
                if (text != null && text.length() > 0) {
                    mResult.append(text);
                }
                
                if (isLast && mListener != null) {
                    final String finalResult = mResult.toString();
                    Log.d(TAG, "最终识别结果: " + finalResult);
                    if (TextUtils.isEmpty(finalResult)) {
                        mListener.onError(0, "未识别到内容，请重试");
                    } else {
                        mListener.onResult(finalResult);
                    }
                }
            }
        }
        
        @Override
        public void onError(SpeechError error) {
            // 详细记录错误信息，便于调试
            Log.e(TAG, "识别出错详情: " + error.getPlainDescription(true));
            Log.e(TAG, "错误码: " + error.getErrorCode() + ", 错误描述: " + error.getErrorDescription());
            
            if (mListener != null) {
                // 对特定错误码给出更友好和具体的提示
                String errorMessage;
                switch (error.getErrorCode()) {
                    case 10118: // 用户没有说话
                        errorMessage = "未检测到语音，请靠近麦克风并大声说话";
                        break;
                    case 20006: // 启动录音失败
                        errorMessage = "启动录音失败，请检查麦克风权限并尝试重启应用";
                        break;
                    case 10114: // 网络异常
                        errorMessage = "网络连接异常，请检查网络设置";
                        break;
                    case 10116: // 音频流错误
                        errorMessage = "音频数据错误，请重试";
                        break;
                    case 20001: // 网络不可用
                        errorMessage = "网络不可用，请检查网络连接";
                        break;
                    default:
                        errorMessage = "语音识别失败: " + error.getPlainDescription(true);
                        break;
                }
                mListener.onError(error.getErrorCode(), errorMessage);
            }
        }
        
        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 事件回调记录详细信息
            String eventInfo = "事件类型: " + eventType;
            if (obj != null) {
                // 尝试提取事件中的额外信息
                for (String key : obj.keySet()) {
                    eventInfo += ", " + key + "=" + obj.get(key);
                }
            }
            Log.d(TAG, "onEvent: " + eventInfo);
        }
    };

    /**
     * 解析讯飞返回的JSON结果
     */
    private String parseResult(String resultJson) {
        StringBuilder ret = new StringBuilder();
        try {
            JSONTokener tokener = new JSONTokener(resultJson);
            JSONObject joResult = new JSONObject(tokener);

            JSONArray words = joResult.getJSONArray("ws");
            for (int i = 0; i < words.length(); i++) {
                JSONArray items = words.getJSONObject(i).getJSONArray("cw");
                JSONObject obj = items.getJSONObject(0);
                ret.append(obj.getString("w"));
            }
        } catch (JSONException e) {
            Log.e(TAG, "解析识别结果异常", e);
            return "";
        }
        return ret.toString();
    }
} 