// Learn cc.Class:
//  - https://docs.cocos.com/creator/manual/en/scripting/class.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 audioEngine = cc.audioEngine ; //require('./audioEngineEx.js')
var  DISPLAY_MODE = cc.Enum({
    LINE: 1,
    FULL: 2,
});
// wordRegex = /(?<=\s|^|\b)(?:[-'",.?;:@%$#&\/]\b|\b[-'",.?;:@%$#&\/]|[A-Za-z0-9]|\([A-Za-z0-9]+\))+(?=\s|$|\b)|(?:[\u4E00-\u9FFF])

const LINE_BEAKER = '<br/>'; // '\n'
const SPACE = '';


/**
 * 1.添加空节点，设置节点大小，拖入该脚本
 * 2.在所建空节点下插入 RichText,RichText的MaxWidth，size设置无效，将会自动调整为父节点大小
 * 3.把建立的子节点RichText拖入本脚本的显示组件里
 */
cc.Class({
    extends: cc.Component,

    properties: {
        // displayMode: {
        //     default: 1,
        //     type: DISPLAY_MODE,
        //     displayName: '显示配置',
        //     tooltip: '是否为多行显示'
        // },
        // testLabel: {
        //     default: null,
        //     type: cc.RichText,
        //     displayName: '显示组件',
        //     tooltip: '仅支持richText组件'
        // },

        richText: {
            default: null,
            type: cc.RichText,
            displayName: '显示组件',
            tooltip: '仅支持richText组件'
        },
        lrcBgColor: {
            default: cc.color(128, 255, 255),
            displayName: '歌词背景颜色',
            tooltip: '歌词背景颜色'
        },
        lrcPlayedColor: {
            default:  cc.color(0, 255, 0),
            displayName: '歌词前景颜色',
            tooltip: '歌词前景颜色'
        },
        lrcPlayingColor: {
            default:  cc.color(0, 255, 0),
            displayName: '歌词高亮颜色',
            tooltip: '歌词高亮颜色'
        },
       
        // foo: {
        //     // ATTRIBUTES:
        //     default: null,        // The default value will be used only when the component attaching
        //                           // to a node for the first time
        //     type: cc.SpriteFrame, // optional, default is typeof default
        //     serializable: true,   // optional, default is true
        // },
        // bar: {
        //     get () {
        //         return this._bar;
        //     },
        //     set (value) {
        //         this._bar = value;
        //     }
        // },
        
    },
    ctor(){
        this._audioClip = null;
        this._currentAudioId = null;
        this._playedContent = [];
        this._remainContent = [];
        this._lrcData = [];
        this.magicHeight = null;
        this.PLAY_MODE = {
            MODE1: 'mode1',
            MODE2: 'mode2',
            MODE3: 'mode3',
        }
        this.__currentInteractivateMode = this.PLAY_MODE.MODE1;
        this.__interactivateMode2Counter = 0;
        this.MODE2_STEP = {
            ONE: 1,
            TWO: 2
        }
    },

    

    initialize(preloadedData) {
        console.log('initialize');
        const t1 = Date.now()
        // const aitem = preloadedData.find(item => {
        //     return item.url == this.audio_url
        // });
        if (this.audio_url) {
            cc.assetManager.loadRemote(this.audio_url, (err, audioClip) => {
                console.log(Date.now() - t1);
                if(err) {
                    // TODO handle error
                    return;
                }
                this._audioClip = audioClip;
                this._audioSource = new cc.AudioSource();
                this._audioSource.clip = this._audioClip;
                this._audioSource.audio.on('ended', () => {
                    console.log('_audioClip ended');
                    this._audioSource.setCurrentTime(0)
                });
                this._audioSource.audio.on('stop', () => {
                    console.log('_audioClip stop');
                });
                // this.currentAudioId = audioEngine.play(this._audioClip, false, 0);
                // audioEngine.pause(this.currentAudioId);
                // audioEngine.setCurrentTime(this.currentAudioId, 0);
                // audioEngine.setVolume(this.currentAudioId, 1);
                
                
                // this.resetLRC();
                // this.renderHighlight();


                // this.currentAudioId = audioEngine.play(audioClip, false, 1);
                // console.log(this.displayMode);
            });
        } 
        
        if (this.accompany_audio_url) {
            cc.assetManager.loadRemote(this.accompany_audio_url, null, (err, audioClip) => {
                if(err) {
                    // TODO handle error
                    return;
                }
                this._audioAcClip = audioClip;
                this._audioACSource = new cc.AudioSource();
                this._audioACSource.clip = this._audioAcClip;
                this._audioACSource.audio.on('ended', () => {
                    console.log('_audioACSource ended');
                    this._audioACSource.setCurrentTime(0)
                });
                this._audioACSource.audio.on('stop', () => {
                    console.log('_audioACSource stop');
                });


                // this.currentAcAudioId = audioEngine.play(this._audioAcClip, false, 0);
                // audioEngine.pause(this.currentAcAudioId);
                // audioEngine.setCurrentTime(this.currentAcAudioId, 0);
                // audioEngine.setVolume(this.currentAcAudioId, 1);
            });
        }
        
    },
    // LIFE-CYCLE CALLBACKS:
    onLoad () {
        window['kk'] = this;
        cc.director.on('STOP_ALL_AUDIO', () => {
            this.pause();
        });
    },

    setPlayInteractivateMode(mode) {
        this.__currentInteractivateMode = mode;
        if ( this._audioSource) {
            this._audioSource.stop();
            this._audioSource.setCurrentTime(0) 
        }
        if (this._audioACSource) {
            this._audioACSource.stop();
            this._audioACSource.setCurrentTime(0)
        }
        
        this.stopAndResetHighLight();
    },
    prepare(gameData){
        // cc.director.on('GAME_RESOURCE_LOADED', () => {
        //     this.initialize();
        // })
        // cc.director.on('GAME_DATA_FETCHED', () => {});

        // const gameData = this.node.parent.getComponent('scene').data;
        // const area = gameData.hotZoneItemArr.find(item => {
        //     return item.itemType === 'karaoke';
        // });
        // this.node.x = area.rect.x;
        // this.node.y = area.rect.y;
        // this.node.width = area.rect.width; 
        // this.node.height = area.rect.width;
        // this.node.parent.zIndex = 99999

        // this.richText.node = new Proxy(this.richText.node , {
        //     set: function(obj, key, val){
        //         obj[key] = val;
        //         return true;
        //     },
        //     get: function(obj, key){
        //         return obj[key]
        //     }
        // })


        
        const karaokeConf = gameData.lrcData
        this._lrcData = karaokeConf.lyrics;
        
        this.audio_url = karaokeConf.audio_url; 
        this.accompany_audio_url = gameData.accompany_audio_url; 
        // this._fontSize = karaokeConf.fontSize || 24;
        // this._lineHeight  = karaokeConf.lineHeight || 32;
        
        this.richText.fontSize = karaokeConf.fontSize || 24;
        this.richText.lineHeight= karaokeConf.lineHeight || 32; 
        // this.richText.node.anchorX = this.richText.node.parent.anchorX;
        // this.richText.node.anchorY = this.richText.node.parent.anchorY;
        // this.labelComp.node.anchorX = 0;
        // this.labelComp.node.anchorY = 1;
        // this.labelComp.node.x = -this.node.width / 2;
        // this.labelComp.node.y = this.node.height / 2;
        const mask = this.getComponent(cc.Mask);
        if (!mask) {
            this.addComponent(cc.Mask);
        }
        
        

        console.log(123123)
        this.richText.maxWidth = this.node.width; 


        this.maskHighlightNode = new cc.Node();
        this.maskHighlightNode.name = 'maskNode'
        this.maskHighlightNode.anchorX = 0;
        this.maskHighlightNode.anchorY = 0;
        this.node.addChild(this.maskHighlightNode);
        this.maskHighlightChildLableNode = new cc.Node(); 
        this.maskHighlightChildLableNode.parent = this.maskHighlightNode; 
        this.maskHighlightNodeLable = this.maskHighlightChildLableNode.addComponent(cc.Label);
        this.maskHighlightNodeLable.node.anchorX = 0;
        this.maskHighlightNodeLable.node.anchorY = 0;
        this.maskHighlightNodeLable.font = this.richText.font;
        this.maskHighlightNodeLable.fontFamily = this.richText.fontFamily;
        this.maskHighlightNodeLable.fontSize = this.richText.fontSize;
        this.maskHighlightNodeLable.useSystemFont = this.richText.useSystemFont;
        this.maskHighlightNodeLable.lineHeight = this.richText.lineHeight;
        this.maskHighlightNodeLable.cacheMode = this.richText.cacheMode;
        this.maskHighlightNodeLable.color =  cc.Color.GREEN;//this.lrcPlayingColor; 
        this.maskHighlightNodeMask = this.maskHighlightNode.addComponent(cc.Mask);
        this.maskHighlightNode.x = 99999;
        this.maskHighlightNode.y = 99999;
        this.maskHighlightNode.zIndex = 99999
        


        this.calcHighlightNode = new cc.Node();
        this.node.addChild(this.calcHighlightNode);
        this.calcHighlightRichText = this.calcHighlightNode.addComponent(cc.RichText);
        const w1 = this.calcHighlightNode.addComponent(cc.Widget);
        w1.left = 0;
        w1.right = 0;
        w1.updateAlignment()
        this.calcHighlightNode.x = 99999;
        this.calcHighlightNode.y = 99999;
        this.calcHighlightRichText.font = this.richText.font;
        this.calcHighlightRichText.fontFamily = this.richText.fontFamily;
        this.calcHighlightRichText.fontSize = this.richText.fontSize;
        this.calcHighlightRichText.useSystemFont = this.richText.useSystemFont;
        this.calcHighlightRichText.lineHeight = this.richText.lineHeight;
        this.calcHighlightRichText.cacheMode = this.richText.cacheMode;
        this.calcHighlightRichText.horizontalAlign = cc.RichText.HorizontalAlign.LEFT;
        this.calcHighlightRichText.maxWidth = this.node.width;
        this.calcHighlightRichText.string = '';

        this.calcSentenceNode = new cc.Node();
        this.node.addChild(this.calcSentenceNode);
        this.calcSentenceRichText = this.calcSentenceNode.addComponent(cc.RichText);
        const w2 = this.calcSentenceNode.addComponent(cc.Widget);
        w2.left = 0;
        w2.right = 0;
        w2.updateAlignment();
        this.calcSentenceNode.x = 99999;
        this.calcSentenceNode.y = 99999;
        this.calcSentenceRichText.font = this.richText.font;
        this.calcSentenceRichText.fontFamily = this.richText.fontFamily;
        this.calcSentenceRichText.fontSize = this.richText.fontSize;
        this.calcSentenceRichText.useSystemFont = this.richText.useSystemFont;
        this.calcSentenceRichText.lineHeight = this.richText.lineHeight;
        this.calcSentenceRichText.cacheMode = this.richText.cacheMode;
        this.calcSentenceRichText.horizontalAlign = cc.RichText.HorizontalAlign.LEFT;
        this.calcSentenceRichText.maxWidth = this.node.width;
        this.calcSentenceRichText.string = '';

        window.k = this.richText;

        this.sentenceContent = {};
        this.sentenceTime = {};
        this.sentenceTimePhase = {};
        this.sentenceTimePhaseIndex = 0;
        const _tmpSentence = [];
        let timePoint = null;
        this._lrcData.forEach((hl, index) => {
            if (index > 0) {
               this._lrcData [index-1].endPoint = hl.time
            }
            
            if (hl.newLine || index == 0) {
                
                let endTime = 0;
                const prevIndex = this.sentenceTimePhaseIndex-1;
                if (prevIndex >= 0) {
                    this.sentenceTimePhase[prevIndex].endTime  = hl.time; 
                }
                this.sentenceTimePhase[this.sentenceTimePhaseIndex] = {
                    startTime: hl.time 
                }
                this.sentenceTimePhaseIndex++;
                hl.sentenceTimePhaseIndex = this.sentenceTimePhaseIndex - 1;
                this.sentenceTime[index] = hl.time
                if (timePoint !== null) {
                    this.sentenceContent[timePoint] = _tmpSentence.join(' ');
                    _tmpSentence.length = 0;
                }
                timePoint = hl.time;
                _tmpSentence.push(`<color=${this.lrcPlayedColor.toHEX()}>${hl.data.trim()}</color>`)
            } else {
                hl.sentenceTimePhaseIndex = this.sentenceTimePhaseIndex - 1; 
                _tmpSentence.push(`<color=${this.lrcPlayedColor.toHEX()}>${hl.data.trim()}</color>`)
            }
            if (timePoint) {
                hl.timePoint = timePoint;
            }
        });
        this.sentenceContent[timePoint] = _tmpSentence.join(' ');
        // console.log('this._lrcData', this._lrcData)
        // console.log('this.sentenceTimePhase', this.sentenceTimePhase)

        
        // this.resetLRC();
        // this.renderLRC(this._lrcData[0].time)
        this.resetLRC();
        this.renderHighlight();

   
        //#region smart flow lrc
        /*
        var timeCallback = function (dt) {
            cc.log("time1: " + dt);
          }
        this.richText.schedule(timeCallback, 1);
        this.richText.unscheduleAllCallbacks();
        const findCurrentData = (time) => {
            if (!time) {
                return;
            }
            let idx = 0;
            let line = this._lrcData[idx];
            while(line){
                if (line.time < time) {
                    idx += 1;
                } else {
                    idx -= 1; 
                    break;
                }
                line = this._lrcData[idx]
                if (!line) {
                    idx -= 1; 
                    break;
                }
            }
            idx = idx < 0 ? 0: idx;
            // console.log(idx, this._remainContent)
            // return this._lrcData[idx];
            return {
                index: idx,
                line: this._remainContent.shift()
            }
        };
        let lastAT = null;
        let lastWT = null
        var timeCallback2 =  (dt) => {
            const t = audioEngine.getCurrentTime(this._currentAudioId);
            if (t == lastAT) {
                return
            }
            lastAT = t;
            // const d = findCurrentData();
            // console.log(this.lastHightLightTimePoint, this._currentHightlightPart);
            if (this._currentHightlightPart && lastWT == this._currentHightlightPart.time) {
                return
            }
            lastWT = this._currentHightlightPart?this._currentHightlightPart.time: null
            let dur = 0;
            if (this._currentHightlightPart) {
                dur = this._currentHightlightPart.endPoint - this._currentHightlightPart.time; 
            }
            let hightlightNode = null;
            let currentHLIndex = null;
            highlightMaskFn = () =>{

            }
            this.richText.node.children.forEach((n, index) => {
                if (n.color.toHEX() == this.lrcPlayingColor.toHEX()) {
                    if (currentHLIndex == index) {
                        return
                    }
                    
                    // const nn = n.convertToNodeSpaceAR(cc.v2(n.x, n.y));
                    // console.log(1, nn.x, nn.y)
                    // const nn2 = n.convertToWorldSpaceAR(cc.v2(n.x, n.y));
                    // console.log(2, nn2.x, nn2.y)
                    // const nn3 = n.convertToNodeSpaceAR(cc.v2(nn2.x, nn2.y));
                    // console.log(3, nn3.x, nn3.y, n.x, n.y)
                    hightlightNode = n
                    currentHLIndex = index;
                    this.maskHighlightNode.width = 0;
                    this.maskHighlightNode.height = n.height;
                    this.maskHighlightNode.x = n.x - this.richText.node.x;
                    this.maskHighlightNode.y = n.y + this.richText.node.y;
                    this.maskHighlightNodeLable.string = n.getComponent(cc.Label).string;
                    this.maskHighlightNodeMask
                    if (dur)  {
                        cc.tween(this.maskHighlightNode)
                        .to(dur, { width: n.width})
                        .start()
                    }
                    
                    // return
                    
                    
                    
                }
            });
            if (hightlightNode) {

            }
          }
        this.richText.schedule(timeCallback2, 1);
        */
        //#endregion
    },
   


    resetLRC(index) {
        this._playedContent = [];
        this._playingContent = [];
        this._remainContent = [];
        // this.lastHightLight = null;
        if (!index) {
            index = 0;
        }
        this._lrcData.slice(0, index).forEach(d => {
            this._playedContent.push({
               ...d 
            });
        });
        this._lrcData.slice(index).forEach(d => {
            this._remainContent.push({
               ...d 
            });
        });
        // this._lrcLine+1 = 0;
        // this._lrcNextLineTime = this._lrcData[0].time;
    },
    findCurrentHighlightByTime(time) {
        // if (time >= this._lrcNextLineTime && this._remainContent.length ) {           
        //     this._lrcLineIndex++;
        //     this._lrcNextLineTime = this._lrcData[this._lrcLineIndex] ? this._lrcData[this._lrcLineIndex].time : 0;
        //     return this._remainContent.shift();
        // }
        if (!time) {
            time = 0;
        }
        let idx = 0;
        let line = this._lrcData[idx];
        if (line.time > time) {
            return 
        }
        // while(line = this._lrcData[idx]){
        //     if (line.time < time) {
        //         idx += 1;
        //     } else {
        //         idx -= 1; 
        //         idx = idx < 0 ? 0 : idx; 
        //         break;
        //     }
        // }
        while(line){
            if (line.time < time) {
                idx += 1;
            } else {
                idx -= 1; 
                break;
            }
            line = this._lrcData[idx]
            if (!line) {
                idx -= 1; 
                break;
            }
        }
        idx = idx < 0 ? 0: idx;
        this.resetLRC(idx)
        // console.log(idx, this._remainContent)
        // return this._lrcData[idx];
        return {
            index: idx,
            line: this._remainContent.shift()
        }



    },
    justifyContentPosition(){
        let {height: h} = this.calcHighlightRichText.node.getContentSize();
        if (this.magicHeight === null) {
            this.magicHeight = h - this.richText.lineHeight; // this.richText._labelHeight
        }
        // let sw = 0;
        // let sh = 0;
        // if (this.calcSentenceRichText.string.trim()) {
        //     const ssize = this.calcSentenceRichText.node.getContentSize(); 
        //     sw = ssize.width;
        //     sh = ssize.height;
        //     this.calcSentenceRichText.string = '';
        //     h = Math.min(h, h - sh + this.node.h)
        // }
        if (this.richText._labelHeight > this.node.height) {
            let posY =  (this.node.height - this.richText._labelHeight ) / 2;
            if (h > this.node.height){
                posY = posY + (h - this.node.height);
            } 
            const b4 = this.richText.node.y;
            // setTimeout(() => {
                this.richText.node.y = posY;// + this.magicHeight;
            // }, 0)
            
            // console.log('this.richText.node.y',b4 , this.richText.node.y, posY)
        }
    },
    findSentenceIndexByWords(s, sentenceIndexObj) {
        if (s == ' ') {
            return
        }
        if (sentenceIndexObj.sentence === s || !sentenceIndexObj.sentence ) {
            sentenceIndexObj.sentenceIndex++;
            if (this._lrcData[sentenceIndexObj.sentenceIndex]) {
                sentenceIndexObj.sentence = this._lrcData[sentenceIndexObj.sentenceIndex].data.trim();
            }
            return;
        } 
        if (s.length < sentenceIndexObj.sentence.length) {
            sentenceIndexObj.sentence = sentenceIndexObj.sentence.replace(s, '')
            return;
        } 
        throw new Error('sssdgmgjgisfgdfh');

    },
    //#region 
    findHighlightStartTimeByString(str, index) {
        const nextLineObj = this.sentenceTime[index + 1];
        if(!nextLineObj) {
            return ;
        }

        let line = null;
        let endIndex = nextLineObj.index;
        while(line = this._lrcData[endIndex]) {
            if (line.newLine || index === 0 ) {
                return line.time 
            }
            endIndex -= 1; 
        }
        return {
            time: line.time,
            index: lineObj.index
        };
    },
    addTouchPlayEvent() {
        const findThisLine = (idx) => {
            do{
                if (!this._lrcData[idx] || this._lrcData[idx].newLine) {
                    break;
                }
            } while(idx-- >= 0);
            return idx < 0 ? 0 : idx;
        }
        const sentenceIndexObj = {
            sentenceIndex: 0,
            sentence: this._lrcData[0].data,
        };
        
        let currentPos = 0;
        let timePoint = this._lrcData[currentPos].time;

        this.richText.node.children.forEach(n => {
            return
            const part = n.getComponent(cc.Label).string; 
            // const tm =this.findHighlightStartTimeByString(part, currentPos);
            // n.off(cc.Node.EventType.TOUCH_START)
            // n.on(cc.Node.EventType.TOUCH_START, () => {
            //     console.log(n._id,ss,breakIndex,tm, idx, n.x,n.y,this.richText.node.children.indexOf(n) );
            //     this.calcSentenceRichText.string = this.sentenceContent[tm];
            //     this.playByTime(tm);
            // });
            // console.log(part);

            const idx = sentenceIndexObj.sentenceIndex;
            const breakIndex = findThisLine(idx);
            const ss = n.getComponent(cc.Label).string;
            if(this._lrcData[breakIndex] || ss != " "){
                const tm = this._lrcData[breakIndex].time
                // this.tttt.push({
                //     x: n.x,
                //     y: n.y,
                //     // n,
                //     ss,
                //     idx,
                //     breakIndex ,
                //     id: n._id
                // }) 
                // console.log(n._id,ss,breakIndex,tm, idx, n.x,n.y);
                n.off(cc.Node.EventType.TOUCH_START)
                n.on(cc.Node.EventType.TOUCH_START, () => {
                    console.log(n._id,ss,breakIndex,tm, idx, n.x,n.y,this.richText.node.children.indexOf(n) );
                    this.calcSentenceRichText.string = this.sentenceContent[tm];
                    this.playByTime(tm);
                });
                const s = n.getComponent(cc.Label).string;
                this.findSentenceIndexByWords(s, sentenceIndexObj);
            }
        });
    },
    getCurrentAudioState() {
        return audioEngine.getState(this._currentAudioId)
    },
    isCurrentAudioSourcePlaying() {
        const adSrc = this.getCurrentPlayingSource();
        return adSrc && adSrc.isPlaying;
    },
    
    //#endregion
    playByTime(index,startTime, endTime){

        if (!startTime) {
            return;
        }
        this.playByTimePhaseOnly = true;
        this.playByTimePhaseStep = this.MODE2_STEP.ONE;
        this.playByTimePhaseIndex = +index;
        if(this.__currentInteractivateMode == this.PLAY_MODE.MODE2){
            this.playMode2WithIndex(this.playByTimePhaseIndex, this.MODE2_STEP.ONE);
        } else {
            // if (audioEngine.getState(this._currentAudioId) === audioEngine.AudioState.STOPPED 
            // || audioEngine.getState(this._currentAudioId) === audioEngine.AudioState.ERROR) {
            //     this.play();
            // } else if (audioEngine.getState(this._currentAudioId) === audioEngine.AudioState.PAUSED){
            //     this.resume();
            // }
            // audioEngine.setCurrentTime(this._currentAudioId, startTime);

            this.resume();
            this.seek(startTime)
        }
        this.playByTimePhaseStartTime = startTime;
        if (endTime) {
            this.playByTimePhaseEndTime = endTime;
        }
        
        this.resetLRC();
    },
    renderHighlight(line) {
        
        if (line) {
            // this._playingContent.push(line);
            this._currentHightlightPart = line;
            this._playingContent = [line];
        } else {
            this._currentHightlightPart = null;
        }
        const playedColor = this.getPlayedColor();
        let played = this._playedContent.map((line, idx) => {
            let words =  `<color=${playedColor} click="clickPlay" param="${line.sentenceTimePhaseIndex}">${line.data.trim()}</color>`;
            // let words =  `<color=${this.lrcPlayedColor.toHEX()} click="clickPlay" param="${line.sentenceTimePhaseIndex}">${line.data.trim()}</color>`;
            if (line.newLine) {
                words = `${words.trim()}${LINE_BEAKER}`;
            }
            return words;
        }).join(SPACE);
        const playingColor = this.getPlayingColor();
        let playing = this._playingContent.map((line, idx) => {
            let words =  `<color=${playingColor} click="clickPlay" param="${line.sentenceTimePhaseIndex}">${line.data.trim()}</color>`;
            // let words =  `<color=${this.lrcPlayingColor.toHEX()} click="clickPlay" param="${line.sentenceTimePhaseIndex}">${line.data.trim()}</color>`;
            if (line.newLine) {
                words = `${words.trim()}${LINE_BEAKER}`;
            }
            return words;
        }).join(SPACE);
        // if (playing.startsWith(LINE_BEAKER)) {
        //     playing = playing.substr(LINE_BEAKER.length);
        // }
        // if (!playing.trim()) {
        //     playing = `${playing} `
        // }
        
        const remained = this._remainContent.map((line, idx) => {
            let words =  `<color=${this.lrcBgColor.toHEX()} click="clickPlay" param="${line.sentenceTimePhaseIndex}">${line.data.trim()}</color>`;
            if (line.newLine) {
                words = `${words.trim()}${LINE_BEAKER}`;
            }
            return words;
        }).join(SPACE);
        if (played.startsWith(LINE_BEAKER)) {
            played = played.substr(LINE_BEAKER.length);
        }
        const textForCalc = `${played}${this._playedContent.length ? " ": ''}${playing}${this._playingContent.length ? " ": ''}`
        // const textForCalc = `${played}${playing}`
       
        // if (this.calcHighlightRichText && this.richText) {
            this.calcHighlightRichText.string = textForCalc;
            this.richText.string = `${textForCalc}${remained}`;
            // console.log(this.richText.node.getContentSize());
            // setTimeout(() => {
            this.justifyContentPosition();
            // }, 0)
        // }
        
    },

    getPlayedColor() {
        return this.lrcPlayedColor.toHEX() 
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE1) {
            return this.lrcPlayingColor.toHEX();
        } else if (this.__currentInteractivateMode == this.PLAY_MODE.MODE2) {
            return this.lrcPlayedColor.toHEX()
        } else {
            return this.lrcPlayedColor.toHEX()
        }
    },

    getPlayingColor() {
        return this.lrcPlayingColor.toHEX();
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE1) {
            return this.lrcPlayingColor.toHEX();
        } else if (this.__currentInteractivateMode == this.PLAY_MODE.MODE2) {
            if (this.playByTimePhaseStep == this.MODE2_STEP.ONE) {
                return this.lrcPlayingColor.toHEX();
            } else {
                return this.lrcPlayedColor.toHEX()
            }
        } else {
            return this.lrcPlayedColor.toHEX()
        }
    },

    getCurrentPlayingSource() {
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE1) {
            return this._audioSource
        }
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE2) {
            // console.error("TODO getCurrentPlayingSource mode2")
            if (!this.playByTimePhaseStep) {
                this.playByTimePhaseStep = this.MODE2_STEP.ONE
            }
            if (this.playByTimePhaseStep & 1) {
                return this._audioSource;
                console.log('change 3 step 1');
            } else {
                return this._audioACSource;
                console.log('change 2 step 1');
            }
        }
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE3) {
            return this._audioACSource;
        }
    },
    renderLRC(t) {
        if (!t) {
            
            if (!this._remainContent.length) {
                return
            }

            const adSrc = this.getCurrentPlayingSource();
            t = adSrc && adSrc.getCurrentTime();

            if (this.PLAY_MODE.MODE1 === this.__currentInteractivateMode 
                || this.PLAY_MODE.MODE3 === this.__currentInteractivateMode ) {
                    if (this.playByTimePhaseEndTime && t > this.playByTimePhaseEndTime) {
                        this.playByTimePhaseEndTime = null;
                        this.stop();
                        return
                    }
            }
            

        }
        if (this.lastHightLightTime == t) {
            return
        }
        this.lastHightLightTime = t
        const data = this.findCurrentHighlightByTime(t);
        if (!data) {
            return
        }
        
        const {line, index} = data;
        // console.log(index, JSON.stringify(line));
        // console.log(t, line, index)
        if (!line) {
            return;
        }
        // if (line.time === this.lastHightLightTimePoint) {
        //     return
        // }
        // this.lastHightLightTimePoint = line.time;

        this.lastHightLight = line.data;
        
        this.renderHighlight(line);
        // this.renderHighlight();
        
    },
    
    playMode2WithIndex(index, step, overrideTime) {
       

        let {startTime, endTime} = this.sentenceTimePhase[index];
        if (overrideTime) {
            startTime = overrideTime; 
        }
        this.playByTimePhaseStartTime = startTime; 
        this.playByTimePhaseEndTime = endTime;
        this.playByTimePhaseStep = step;
        this.playByTimePhaseIndex = index;
        // audioEngine.stop(this._currentAudioId);
        const adSrc = this.getCurrentPlayingSource();
        const ct = adSrc ? adSrc.getCurrentTime() : 0;
        if (!ct) {
            adSrc.stop()
            adSrc.play()
        } else {
            adSrc.resume()
        } 
        // if (step & 1) {
        //     this.currentPlayTimestampSeeked = false;
        //     this.play()
        //     console.log('change 3 step 1');
        // } else {
        //     this.play()
        //     console.log('change 2 step 1');
        // }
        this.seek(startTime);

    },
  
    checkMode2() {
        const adSrc = this.getCurrentPlayingSource(); 
        if (!adSrc) {
            return
        }
        const t = adSrc.getCurrentTime();
        if (!t) {
            return;
        }
        // if (this.lastHightLightTime == t) {
        //     return
        // }
        // this.lastHightLightTime = t
        if (this.playByTimePhaseEndTime && t > this.playByTimePhaseEndTime) {
            this.pause();
            // if (this.PLAY_MODE.MODE2 === this.__currentInteractivateMode) {
            // }
            if (this.playByTimePhaseStep & 1) {
                // this.currentAudioId = audioEngine.play(this._audioAcClip, false, 1);
                this.playByTimePhaseStep = this.MODE2_STEP.TWO;
            } else {
                if (this.playByTimePhaseOnly) {
                    this.playByTimePhaseOnly = false;
                    return;
                }
                this.playByTimePhaseStep = this.MODE2_STEP.ONE;
                this.playByTimePhaseIndex += 1;
            }
            this.playMode2WithIndex(this.playByTimePhaseIndex, this.playByTimePhaseStep)
        }
    },
    ___play() {
        // audioEngine.stop(this._currentAudioId);
        this.stop()
        this.currentPlayTimestampSeeked = true;
        if (!this.currentPlayTimestampCheckPoint) {
            this.currentPlayTimestampCheckPoint = 0;
        }
        this._currentAudioId = null;
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE1) {
            this._currentAudioId = audioEngine.play(this._audioClip, false, 1); 
            
            console.log('change play 1', this._currentAudioId);
        }
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE2) {
            this.playMode2WithIndex(0, this.MODE2_STEP.ONE);
        }
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE3) {
            this._currentAudioId = audioEngine.play(this._audioAcClip, false, 1);
            console.log('change play 3', this._currentAudioId);
        }
        
        this.resetLRC();
    },
    stopAndResetHighLight() {
        const adSrc = this.getCurrentPlayingSource();
        adSrc && adSrc.stop();
        this.playByTimePhaseEndTime = null;
        this.playByTimePhaseOnly = false;
        this.playByTimePhaseStep = this.MODE2_STEP.ONE; 
        this.playByTimePhaseIndex = 0;
        this.resetLRC();
        this.renderHighlight();
    },
    stop() {
        const adSrc = this.getCurrentPlayingSource();
        adSrc.stop();
        
    }, 
    pause() {
        const adSrc = this.getCurrentPlayingSource();
        adSrc.pause();
        
    },
    resume() {
        const adSrc = this.getCurrentPlayingSource();
        const ct = adSrc && adSrc.getCurrentTime();
        if (this.__currentInteractivateMode == this.PLAY_MODE.MODE2) {
            if (!this.playByTimePhaseStep) {
                this.playByTimePhaseStep = this.MODE2_STEP.ONE; 
            }
            if (!this.playByTimePhaseIndex) {
                this.playByTimePhaseIndex = 0; 
            }
            this.playMode2WithIndex(this.playByTimePhaseIndex, this.playByTimePhaseStep, ct);
        } else {
            if (!ct) {
                adSrc.stop()
                adSrc.play()
            } else {
                adSrc.resume()
            } 
        }
        
        this.resetLRC();
    },
    seek(time) {
        const adSrc = this.getCurrentPlayingSource();
        adSrc.setCurrentTime(time);
    },

    start () {
        // this.node.width = this.node.width * .6

    },

    update (dt) {
        if (this.PLAY_MODE.MODE2 === this.__currentInteractivateMode) {
            this.checkMode2();
        }
        // if (this.PLAY_MODE.MODE1 === this.__currentInteractivateMode 
        //     || this.PLAY_MODE.MODE3 === this.__currentInteractivateMode ) {
        //     const t = audioEngine.getCurrentTime(this._currentAudioId);
        //     if (this.playByTimePhaseEndTime && t > this.playByTimePhaseEndTime) {
        //         this.playByTimePhaseEndTime = null;
        //         this.stop();
        //         audioEngine.setCurrentTime(this._currentAudioId, audioEngine.getCurrentTime() + dt);
        //         return
        //     }
        // }
        
        this.renderLRC();
        
    },
    onDestroy() {
        // audioEngine.uncache(this.audioUrl); 
        audioEngine.stop(this._currentAudioId);
    }
});
