// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;
import { speechToTextRequest } from "./SpeechAssessment_DG_FAF"
@ccclass
export default class NewClass extends cc.Component {

    canvas: cc.Node = null; // 根节点
    buttonsContainer: cc.Node = null; // 按钮布局容器
    recordButton: cc.Node = null; // 录音按钮
    playRecordButton: cc.Node = null; // 重新录音按钮
    editBox: cc.Node = null; // 重新录音按钮
    maskBg: cc.Node = null; // 遮罩层
    editBoxContainer: cc.Node = null; // 编辑框容器
    submitBtn: cc.Node = null; // 提交按钮
    msgConvertingNode: cc.Node = null; // 评测中提示信息

    recordUrl: String = ""; // 语音转写的URL
    recordText: String = ""; // 语音转写的文本
    evaText: String = ""; // 评测的文本

    // LIFE-CYCLE CALLBACKS:

    // onLoad () {}

    start () {
        // 各个实例
        this.editBoxContainer = cc.find("SysEditbox", this.node);
        this.canvas = cc.find("Canvas");
        this.buttonsContainer = cc.find("Buttons", this.node);
        this.submitBtn = cc.find("btnSubmit", this.editBoxContainer);
        this.recordButton = cc.find("Buttons/Record", this.node);
        this.playRecordButton = cc.find("Buttons/PlayRecord", this.node);
        this.editBox = cc.find("textEditBox", this.editBoxContainer);
        this.editBox.getComponent(cc.EditBox).enabled = false;
        this.msgConvertingNode = cc.find("MessageConverting", this.node);

        this.msgConvertingNode.active = false;
        this.playRecordButton.active = false;

        // 遮罩层
        this.maskBg = cc.find("mask_bg", this.node);
        this.initMask();
        // 
        this.initSys();

        // 添加事件监听
        this.initEventListener();
    }

    // 遮罩层
    initMask() {
        this.maskBg.width = 999999;
        this.maskBg.height = 999999;
    }

    // 初始化输入框等
    initSys() {
        this.node.active = false;
        this.node.x = 0;
        this.node.y = 0
        this.editBoxContainer.x = 0;
        this.editBoxContainer.y = 0;
        this.editBoxContainer.active = true;
        this.editBoxContainer.y = this.canvas.height / 2 * this.canvas.scaleY - this.editBoxContainer.height / 2 - 150;

        // 默认显示返回图标
        const btnOK = cc.find("btnSubmit/ok", this.editBoxContainer);
        const btnReturn = cc.find("btnSubmit/return", this.editBoxContainer);
        btnOK.active = false;
        btnReturn.active = true;

    }

    // 显示键盘
    show(options) {
        if(this.isShow) {
            // 如果正在显示 不处理
            return;
        }
        this.recordUrl = options.recordUrl;
        this.recordText = options.recordText;
        this.evaText = options.evaText;

        this.preLoadAudio(this.recordUrl);

        // 隐藏背景
        this.maskBg.opacity = 1;
        // 隐藏节点
        this.node.opacity = 1;
        // 显示组件
        this.node.active = true;
        // 显示标记位置为true
        this.isShow = true;

        // 设置默认显示文字
        this.setEditboxString(this.recordText);

        // 更新输入图标 空字符显示返回 非空显示对号
        this.updateSubmitAndReturnButtons();

        // 之前没有录音 只显示录音按钮
        if(this.recordUrl == "") {
            // 显示录音按钮
            this.recordButton.active = true;
            this.updatePlayAndReplayButtons("record", "init");
            // 隐藏播放按钮
            this.playRecordButton.active = false;
            this.updatePlayAndReplayButtons("play", "init");
        } else {
            // 显示录音按钮
            this.recordButton.active = true;
            this.updatePlayAndReplayButtons("record", "reRec");
            // 隐藏播放按钮
            this.playRecordButton.active = true;
            this.updatePlayAndReplayButtons("play", "init");
        }

        cc.tween(this.maskBg).to(0.1, {opacity: 255}).start();
        cc.tween(this.node).to(0.1, {opacity: 255}).start();
    }

    // 隐藏键盘
    hide() {
        if(!this.isShow) {
            // 如果已经隐藏 不做处理
            return;
        }
        
        // 显示标记位置为 false
        this.isShow = false;
        cc.tween(this.node).to(0.1, {opacity: 1}).call(()=>{
            this.node.active = false;
        }).start();
        cc.tween(this.maskBg).to(0.1, {opacity: 1}).start();
    }
    
    // 事件注册
    initEventListener() {
        // 订阅节点事件监听 - 外部调用键盘时会发送事件消息
        this.node.on("show", (defaultText)=>{
            this.show(defaultText);
        })

        this.recordButton.on("click", ()=>{
            if(!this.isRecording) {
                this.startRealTimeTranslate();
            } else {
                this.stopRealTimeTranslate();
            }
        })

        this.playRecordButton.on("click", ()=>{
            if(!this.isPlaying) {
                this.playRecord()
            } else {
                this.stopPlayingRecord()
            }
        })
        
        this.submitBtn.on("click", ()=>{
            const text = this.editBox.getComponent(cc.EditBox).textLabel;
            // 发送消息给订阅者
            this.node.emit("onFinish", {
                evaText: this.evaText,
                recordUrl: this.recordUrl,
                recordText: this.recordText
            });
            // 隐藏键盘
            this.hide();
        })
    }

    // 根据输入框内容 更新右侧按钮状态
    updateSubmitAndReturnButtons() {
        const btnOK = cc.find("btnSubmit/ok", this.editBoxContainer);
        const btnReturn = cc.find("btnSubmit/return", this.editBoxContainer);
        if(this.recordText == "") {
            btnOK.active = false;
            btnReturn.active = true;
        } else {
            btnOK.active = true;
            btnReturn.active = false;
        }
    }

    // 更新录音、回放按钮状态
    updatePlayAndReplayButtons(type, status) {
        const recRec = cc.find("record", this.recordButton); // 录音按钮
        const reRecRec = cc.find("re-record", this.recordButton); // 重录按钮
        const recRecording = cc.find("recording", this.recordButton); //录音中按钮
        const recProgress = cc.find("progress", this.recordButton); //录音中进度条
        const play = cc.find("play", this.playRecordButton); // 播放按钮
        const playing = cc.find("playing", this.playRecordButton); //播放中按钮
        const playProgress = cc.find("progress", this.playRecordButton); //播放中进度条

        if(type == "record") {
            switch(status) {
                case "init":
                    recRec.active = true;
                    reRecRec.active = false;
                    recRecording.active = false;
                    recProgress.active = false;
                    break;
                case "recording":
                    recRec.active = false;
                    reRecRec.active = false;
                    recRecording.active = true;
                    recProgress.active = true;
                    break;
                case "reRec":
                    recRec.active = false;
                    reRecRec.active = true;
                    recRecording.active = false;
                    recProgress.active = false;
                    break;
                default:;
            }
        } else {
            switch(status) {
                case "init":
                    play.active = true;
                    playing.active = false;
                    playProgress.active = false;
                    break;
                case "playing":
                    play.active = false;
                    playing.active = true;
                    playProgress.active = true;
                    break;
                default:;
            }
        }
    }

    intervalIDTranslate = null;
    recordTime = 10 * 1000;
    handlerSpeach = null;
    isRecording = false;
    // 开始实时转写
    startRealTimeTranslate() {
        // 隐藏提交按钮 避免发生意外
        this.submitBtn.active = false;
        // 显示录音按钮
        this.recordButton.active = true;
        this.updatePlayAndReplayButtons("record", "recording");
        // 隐藏播放按钮
        this.playRecordButton.active = false;
        this.updatePlayAndReplayButtons("play", "init");
        this.isRecording = true;
        this.handlerSpeach = speechToTextRequest();
        const recProgress = cc.find("progress", this.recordButton); //录音中进度条

        if(this.intervalIDTranslate) {
            clearInterval(this.intervalIDTranslate);
            this.intervalIDTranslate = null;
        }
        let _recordTime = this.recordTime;
        this.intervalIDTranslate = setInterval(()=>{
            _recordTime -= 30;
            let progress = (this.recordTime - _recordTime) / this.recordTime;
            if(_recordTime <= 0 || (1 - progress) < 0) {
                this.stopRealTimeTranslate()
            } else {
                recProgress.getComponent(cc.Sprite).fillRange = 1 - progress;
            }
        }, 30)
    };

    // 停止实时转写
    stopRealTimeTranslate() {
        if(this.handlerSpeach) {
            // 隐藏下面两个按钮
            this.recordButton.active = false;
            this.playRecordButton.active = false;
            // 显示测评中按钮
            this.msgConvertingNode.active = true;
            // 停止计时【停止倒计时，防止二次出发结束录音】
            if(this.intervalIDTranslate) {
                clearInterval(this.intervalIDTranslate);
                this.intervalIDTranslate = null;
            }
            // 调用中间层返回停止方法，参数为异步回调，给到转换结果
            this.handlerSpeach((e)=>{
                // 隐藏测评中按钮
                this.msgConvertingNode.active = false;

                console.log("Record result", e)
                let obj = { text: "", audioUrl: "" }
                try {
                    obj = JSON.parse(e)
                } catch(err) {
                    console.log(err)
                }
                this.setEditboxString(obj.text);
                this.recordUrl = obj.audioUrl;
                if(this.recordUrl) {
                    this.preLoadAudio(this.recordUrl);
                }
                
                // 录音结束后恢复按钮状态
                this.isRecording = false;
                // 结束录音 显示提交按钮
                this.submitBtn.active = true;
                // 显示录音按钮
                this.recordButton.active = true;
                if(this.recordUrl) {
                    this.updatePlayAndReplayButtons("record", "reRec");
                } else {
                    this.updatePlayAndReplayButtons("record", "init");
                }
                // 隐藏播放按钮
                this.playRecordButton.active = true;
                this.updatePlayAndReplayButtons("play", "init");
            });
            this.handlerSpeach = null;
        }
        
    }

    intervalIDPlayRecord = null;
    currentPlayAudioId = null;
    // 听回放
    async playRecord() {
        // 隐藏提交按钮 避免发生意外
        this.submitBtn.active = false;
        // 显示录音按钮
        this.recordButton.active = false;
        this.updatePlayAndReplayButtons("record", "reRec");
        // 隐藏播放按钮
        this.playRecordButton.active = true;
        this.updatePlayAndReplayButtons("play", "playing");

        // 先获取音频流 获取时长
        const audioClip = await this.asyncGetAudioClip(this.recordUrl);
        const duration = audioClip.duration;
        // 播放音频
        this.currentPlayAudioId = this.playAudio(audioClip, ()=>{
            // 完成后清空音频id
            this.currentPlayAudioId = null;
            this.stopPlayingRecord();
        })

        // 循环更新进度条
        this.isPlaying = true;
        const playProgress = cc.find("progress", this.playRecordButton); //播放中进度条
        if(this.intervalIDPlayRecord) {
            clearInterval(this.intervalIDPlayRecord);
            this.intervalIDPlayRecord = null;
        }
        let audioDuration = duration * 1000;
        let _recordTime = audioDuration;
        this.intervalIDPlayRecord = setInterval(()=>{
            _recordTime -= 30;
            let progress = (audioDuration - _recordTime) / audioDuration;
            
            if(_recordTime <= 0 || (1 - progress) < 0) {
                this.stopPlayingRecord();
            } else {
                playProgress.getComponent(cc.Sprite).fillRange = 1 - progress;
            }
        }, 30)
    }

    // 停止听回放
    stopPlayingRecord() {
        // 如果当前正在播放，则停止
        if(this.currentPlayAudioId) {
            cc.audioEngine.stop(this.currentPlayAudioId)
            this.currentPlayAudioId = null;
        }

        // 显示提交按钮
        this.submitBtn.active = true;
        // 显示录音按钮
        this.recordButton.active = true;
        this.updatePlayAndReplayButtons("record", "reRec");
        // 隐藏播放按钮
        this.playRecordButton.active = true;
        this.updatePlayAndReplayButtons("play", "init");
        this.isPlaying = false;
        if(this.intervalIDPlayRecord) {
            clearInterval(this.intervalIDPlayRecord);
            this.intervalIDPlayRecord = null;
        }
    }

    // 设置输入框内容
    setEditboxString(string) {
        this.recordText = string;
        this.updateSubmitAndReturnButtons();
        this.editBox.getComponent(cc.EditBox).string = string
    }

    // 加载音频
    playAudio(audioClip, cb) {
        const audioId = cc.audioEngine.play(audioClip, false, 1);
        if (cb) {
            cc.audioEngine.setFinishCallback(audioId, () => {
                cb();
            });
        }
        return audioId
    }

    asyncGetAudioClip(audio_url) {
        return new Promise((resovle, reject) => {
            cc.assetManager.loadRemote(audio_url, (err, audioClip) => {
                const audioId = cc.audioEngine.play(audioClip, false, 0);
                setTimeout(() => {
                    if(audioId) {
                        cc.audioEngine.stop(audioId)
                    }
                    resovle(audioClip)
                }, 10);
            });
        })
    }

    // 预加载音频
    preLoadAudio(audio_url) {
        if(audio_url) {
            cc.assetManager.loadRemote(audio_url, ()=>{})
        }
    }

    // 页面销毁前清掉计时器
    onDestroy() {
        if(this.intervalIDTranslate) {
            clearInterval(this.intervalIDTranslate)
        }
        if(this.intervalIDPlayRecord) {
            clearInterval(this.intervalIDPlayRecord)
        }
    }
    // update (dt) {}
}
