package com.yeejoin.amos.boot.module.jcs.biz.audioToText;

import com.alibaba.nls.client.protocol.asr.SpeechTranscriberListener;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yeejoin.amos.component.rule.config.RuleConfig;
import com.yeejoin.amos.speech.SpeechTranscriber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.typroject.tyboot.component.emq.EmqKeeper;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

@Component
public class AudioToText {
    private static final Logger logger = LoggerFactory.getLogger(AudioToText.class);
    //翻译成功响应码
    public static final int RESULT_SUCCESS_CODE = 20000000;
    /* //关键字
     public static final ThreadLocal<AudioKeyWord> keyWordThreadLocal = new ThreadLocal<>();
     //语句
     public static final ThreadLocal<List<AudioRecord>> recordThreadLocal = new ThreadLocal<>();*/

    @Autowired
    private EmqKeeper emqKeeper;

    public void convert() {
        List<AudioRecord> audioRecords = new ArrayList<>();
        AudioKeyWord audioKeyWord = new AudioKeyWord();

        String filepath = "D:\\ffmpeg-4.4-full_build-shared\\bin\\out.pcm";
        SpeechTranscriber transcriber = new SpeechTranscriber(new File(filepath), new SpeechTranscriberListener() {
            /**
             * 语音识别过程中返回的结果。仅当setEnableIntermediateResult为true时，才会返回该消息。
             */
            @Override
            public void onTranscriptionResultChange(SpeechTranscriberResponse response) {
                logger.warn("语音识别过程中返回的结果");
                logger.warn("task_id: " + response.getTaskId() +
                        ", name: " + response.getName() +
                        //状态码“20000000”表示正常识别。
                        ", status: " + response.getStatus() +
                        //句子编号，从1开始递增。
                        ", index: " + response.getTransSentenceIndex() +
                        //当前的识别结果。
                        ", result: " + response.getTransSentenceText() +
                        //当前已处理的音频时长，单位为毫秒。
                        ", time: " + response.getTransSentenceTime());
                if (response.getStatus() == RESULT_SUCCESS_CODE) {
                    sendToMqtt(response, audioRecords);
                    extractKeyWord(response, audioKeyWord);
                } else {
                    logger.error("异常的相应结果，响应码：" + response.getStatus());
                }
            }

            /**
             * 服务端准备好了进行识别
             */
            @Override
            public void onTranscriberStart(SpeechTranscriberResponse response) {
                logger.warn("服务端准备好了进行识别");
                logger.warn("task_id: " + response.getTaskId()
                        + ", name: " + response.getName()
                        + ", status: " + response.getStatus());
            }

            /**
             * 服务端检测到了一句话的开始
             */
            @Override
            public void onSentenceBegin(SpeechTranscriberResponse response) {
                logger.warn("服务端检测到了一句话的开始");
                logger.warn("task_id: " + response.getTaskId()
                        + ", name: " + response.getName()
                        + ", status: " + response.getStatus());
            }

            /**
             * 服务端检测到了一句话的结束
             * 识别出一句话。服务端会智能断句，当识别到一句话结束时会返回此消息。
             */
            @Override
            public void onSentenceEnd(SpeechTranscriberResponse response) {
                logger.warn("服务端检测到了一句话的结束");
                logger.warn("task_id: " + response.getTaskId() +
                        ", name: " + response.getName() +
                        //状态码“20000000”表示正常识别。
                        ", status: " + response.getStatus() +
                        //句子编号，从1开始递增。
                        ", index: " + response.getTransSentenceIndex() +
                        //当前的识别结果。
                        ", result: " + response.getTransSentenceText() +
                        //置信度
                        ", confidence: " + response.getConfidence() +
                        //开始时间
                        ", begin_time: " + response.getSentenceBeginTime() +
                        //当前已处理的音频时长，单位为毫秒。
                        ", time: " + response.getTransSentenceTime());
            }

            /**
             * 识别结束后返回的最终结果
             */
            @Override
            public void onTranscriptionComplete(SpeechTranscriberResponse response) {
                logger.warn("识别结束后返回的最终结果");
                logger.warn("task_id: " + response.getTaskId()
                        + ", name: " + response.getName()
                        + ", status: " + response.getStatus()
                        + ",result:" + response.getTransSentenceText());
            }

            /**
             * 失败处理
             */
            @Override
            public void onFail(SpeechTranscriberResponse response) {
                logger.error("失败处理");
                logger.error("task_id: " + response.getTaskId()
                        + ", status: " + response.getStatus()
                        + ", status_text: " + response.getStatusText());
            }
        });
        transcriber.process();
    }

    /**
     * 发送结果至mqtt
     *
     * @param response     语音句子识别返回结果
     * @param audioRecords 历史识别记录
     */
    @Async
    public void sendToMqtt(SpeechTranscriberResponse response, List<AudioRecord> audioRecords) {
        AudioRecord audioRecord = new AudioRecord.AudioRecordBuilder()
                .type(0) // TODO 区别说话角色
                .taskId(response.getTaskId())
                .name(response.getName())
                .status(response.getStatus())
                .index(response.getTransSentenceIndex())
                .message(response.getTransSentenceText())
                .confidence(response.getConfidence())
                .beginTime(response.getSentenceBeginTime())
                .time(response.getTransSentenceTime())
                .build();
        audioRecords.set(audioRecord.getIndex(), audioRecord);
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            emqKeeper.getMqttClient().publish(
                    MessageType.RECORD.getName(),
                    objectMapper.writeValueAsString(audioRecord).getBytes(),
                    RuleConfig.DEFAULT_QOS, true);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("发送音频识别结果消息异常，原因：" + e.getMessage());
        }
    }

    /**
     * 提取关键字，并发送至mqtt
     *
     * @param response     语音句子识别返回结果
     * @param audioKeyWord //关键字结果集
     */
    @Async
    public void extractKeyWord(SpeechTranscriberResponse response, AudioKeyWord audioKeyWord) {
        try {
            String result = response.getTransSentenceText();
            //寻找关键字
            for (MessageKeywords messageKeyword : MessageKeywords.values()) {
                for (String keyword : messageKeyword.getKeyword()) {
                    int index = result.indexOf(keyword);
                    //TODO 暂时截取到末尾
                    if (index != -1) {
                        String keywordValue = result.substring(index);
                        audioKeyWord.getValues().get(messageKeyword.getType()).add(keywordValue);
                    }
                }
            }
            ObjectMapper objectMapper = new ObjectMapper();
            byte[] bytes = objectMapper.writeValueAsString(audioKeyWord.getValues()).getBytes();
            emqKeeper.getMqttClient().publish(
                    MessageType.KEYWORD.getName(),
                    bytes,
                    RuleConfig.DEFAULT_QOS, true);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("发送音频关键字消息异常，原因：" + e.getMessage());
        }
    }
}
