package com.example.ai_assistant_plugin;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.idst.nui.AsrResult;
import com.alibaba.idst.nui.Constants;
import com.alibaba.idst.nui.INativeNuiCallback;
import com.alibaba.idst.nui.KwsResult;

import io.flutter.plugin.common.MethodChannel;

public class AsrCallBack implements INativeNuiCallback {

    private static final String TAG = "AliAsr";
    private final static int ASR_SAMPLE_RATE = 16000;
    private final static int ASR_WAVE_FRAM_SIZE = 20 * 2 * 1 * ASR_SAMPLE_RATE / 1000; //20ms audio for 16k/16bit/mono
    private AudioRecord asrAudioRecorder = null;
    private MethodChannel channel;
    private String asrText = "";
    private Handler handler = new Handler(Looper.getMainLooper());

    public AsrCallBack(MethodChannel channel) {
        this.channel = channel;
    }

    @Override
    public void onNuiEventCallback(Constants.NuiEvent event, final int resultCode,
                                   final int arg2, KwsResult kwsResult,
                                   AsrResult asrResult) {
        Log.i(TAG, "event=" + event + " resultCode=" + resultCode);
        if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_STARTED) {
            asrText = "";
        } else if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_COMPLETE) {

        } else if (event == Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT) {
            JSONObject jsonObject = JSON.parseObject(asrResult.allResponse);
            JSONObject payload = jsonObject.getJSONObject("payload");
            String result = payload.getString("result");
            if (channel != null && result != null && !result.isBlank()) {
                handler.post(() -> channel.invokeMethod("onAsrResult", asrText + result));
            }
        } else if (event == Constants.NuiEvent.EVENT_SENTENCE_END) {
            JSONObject jsonObject = JSON.parseObject(asrResult.allResponse);
            JSONObject payload = jsonObject.getJSONObject("payload");
            String result = payload.getString("result");
            if (channel != null && result != null && !result.isBlank()) {
                asrText += result;
                handler.post(() -> channel.invokeMethod("onAsrResult", asrText));
            }
        } else if (event == Constants.NuiEvent.EVENT_VAD_START) {

        } else if (event == Constants.NuiEvent.EVENT_VAD_END) {

        } else if (event == Constants.NuiEvent.EVENT_ASR_ERROR) {

        } else if (event == Constants.NuiEvent.EVENT_MIC_ERROR) {

        } else if (event == Constants.NuiEvent.EVENT_DIALOG_EX) { /* unused */
            Log.i(TAG, "dialog extra message = " + asrResult.asrResult);
        }
    }

    //当调用NativeNui的start后，会一定时间反复回调该接口，底层会提供buffer并告知这次需要数据的长度
    //返回值告知底层读了多少数据，应该尽量保证return的长度等于需要的长度，如果返回<=0，则表示出错
    @Override
    public int onNuiNeedAudioData(byte[] buffer, int len) {
        if (asrAudioRecorder == null) {
            return -1;
        }
        if (asrAudioRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
            Log.e(TAG, "audio recorder not init");
            return -1;
        }
        return asrAudioRecorder.read(buffer, 0, len);
    }

    //当录音状态发送变化的时候调用
    @Override
    public void onNuiAudioStateChanged(Constants.AudioState state) {
        Log.i(TAG, "onNuiAudioStateChanged");
        if (state == Constants.AudioState.STATE_OPEN) {
            Log.i(TAG, "audio recorder start");
            asrAudioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
                    ASR_SAMPLE_RATE,
                    AudioFormat.CHANNEL_IN_MONO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    ASR_WAVE_FRAM_SIZE * 4);
            asrAudioRecorder.startRecording();
            Log.i(TAG, "audio recorder start done");
        } else if (state == Constants.AudioState.STATE_CLOSE) {
            Log.i(TAG, "audio recorder close");
            if (asrAudioRecorder != null) {
                asrAudioRecorder.release();
            }
        } else if (state == Constants.AudioState.STATE_PAUSE) {
            Log.i(TAG, "audio recorder pause");
            if (asrAudioRecorder != null) {
                asrAudioRecorder.stop();
            }
        }
    }

    @Override
    public void onNuiAudioRMSChanged(float val) {
//        Log.i(TAG, "onNuiAudioRMSChanged vol " + val);
    }

    @Override
    public void onNuiVprEventCallback(Constants.NuiVprEvent event) {
        Log.i(TAG, "onNuiVprEventCallback event " + event);
    }

    @Override
    public void onNuiLogTrackCallback(Constants.LogLevel level, String log) {
        Log.i(TAG, "onNuiLogTrackCallback log level:" + level + ", message -> " + log);
    }

    public void release() {
        // 释放音频录制资源
        if (asrAudioRecorder != null) {
            try {
                asrAudioRecorder.stop();
            } catch (Exception e) {
                Log.e(TAG, "release error", e);
            }
            asrAudioRecorder.release();
            asrAudioRecorder = null;
        }
        channel = null;
        asrText = null;
    }
}
