import { asyncDelay, onHomeworkFinish, RandomInt } from "../script/util";
import { MyCocosSceneComponent } from "../script/MyCocosSceneComponent";
import Game from "./tool/Game";
import pg from "./tool/pg";

const { ccclass, property } = cc._decorator;
@ccclass
export default class SceneComponent extends MyCocosSceneComponent {

    addPreloadImage() {
        // TODO 根据自己的配置预加载图片资源
        let arr = [];
        // this._imageResList.push(...arr);
    }

    addPreloadAudio() {
        // TODO 根据自己的配置预加载音频资源
        let arr = [];
        // this._audioResList.push(...arr);
    }

    addPreloadAnima() {

    }

    onLoadEnd() {
        // TODO 加载完成后的逻辑写在这里, 下面的代码仅供参考
        this.initData();
        this.initView();
        this.initEvent();
        this.gameStart(false);
    }
    protected onDestroy(): void {
        pg.event.clear();
    }


    //--------------------------------------INIT--------------------------------
    @property(cc.Node)
    layout_game: cc.Node = null;
    @property(cc.Node)
    layout_start: cc.Node = null;
    @property(cc.Node)
    layout_finish: cc.Node = null;
    @property(cc.Node)
    card_node: cc.Node = null;


    private openSingle: boolean;
    private openPlay: boolean;
    private openShowVoice: boolean;
    private readCount: number;
    initData() {
        Game.getIns().init(this.data);
        Game.getIns().reset({ w: this.layout_game.width, h: this.layout_game.height });
        this.hideDouble();
        this.openSingle = false;
        this.openPlay = false;
        this.readCount = 0;
        this.scale = 1;
        this.lastMove = cc.v2(0, 0)
    }
    async initView() {
        this.updateDoubleBtns();
        this.initQuestions();
    }
    exitGame() {
        const middleLayer = cc.find('middleLayer')?.getComponent('middleLayer');
        if (middleLayer) {
            // 有些模板需要在返回时上报数据，直接把数据作为参数传入就可以了
            middleLayer.exitGame({ totalCount: this.readCount });//this.resData
        } else {
            console.log("==触发返回事件==");
        }
    }
    initEvent() {
        let btns = pg.view.find(this, 'btns');
        pg.view.touchOn(pg.view.find(this, 'btn_return'), this.exitGame, this);
        pg.view.touchOn(pg.view.find(btns, 'btn_next_1'), this.onTouchBtnNext, this);
        pg.view.touchOn(pg.view.find(btns, 'btn_pre_1'), this.onTouchBtnPre, this);
        this.initFingerDouble();
        pg.view.touchOn(pg.view.find(btns, 'btn_single_0'), this.onTouchBtnSingle, this);
        pg.view.touchOn(pg.view.find(btns, 'btn_single_1'), this.onTouchBtnSingle, this);
        pg.view.touchOn(pg.view.find(btns, 'btn_play_0'), this.onTouchBtnPlay, this);
        pg.view.touchOn(pg.view.find(btns, 'btn_play_1'), this.onTouchBtnPlay, this);
    }
    initQuestions() {
        // 直接渲染多个页面
        let page = pg.view.find(this.layout_game, 'page');
        let show_area = pg.view.find(this.layout_game, 'show_area');
        let list = Game.getIns().getQuestions();
        let pageNum = Game.getIns().getCurrentPageNum();
        for (let i = 0; i < list.length; i++) {
            let node = cc.instantiate(page);
            let data = list[i];
            node.data = data;
            pg.view.addChild(show_area, node, list.length - i);
            this.updateImage(node, data)
        }
    }
    gameStart(isPlayAudio = true) {
        this.updateTouch();

        this.hideDouble();
        this.openSingle = false;
        this.onStopAllAudio();
        // this.onPlayAllAudio();
    }
    private gameOver() {
        onHomeworkFinish({})
    }


    //-------------------------------------双指缩放------------------------------

    private openDouble: boolean;
    showDouble() {
        this.openDouble = true;
    }
    hideDouble() {
        this.openDouble = false;
    }
    // 初始化双指操作
    initFingerDouble() {
        let btns = pg.view.find(this, 'btns');
        pg.view.touchOn(pg.view.find(btns, 'btn_double_0'), this.onTouchBtnDouble, this);
        pg.view.touchOn(pg.view.find(btns, 'btn_double_1'), this.onTouchBtnDouble, this);
        // 触摸监听
        pg.view.find(btns, 'panel_double').on('touchstart', this.onTouchPanelStart, this);
        pg.view.find(btns, 'panel_double').on('touchmove', this.onTouchPanelMove, this);
        pg.view.find(btns, 'panel_double').on('touchend', this.onTouchPanelEnd, this);
    }
    // 点击双指触摸开关
    onTouchBtnDouble() {
        //允许双指操作
        this.openDouble = !this.openDouble;
        if (this.openDouble) {
            this.openSingle = false;
            this.onStopAllAudio();
            this.updateTips('开启手动缩放模式');
        }
    }

    // 手指1
    private startPos1: any;
    // 手指2
    private startPos2: any;
    // 手指间距
    private pointsDis: any;
    // 开始触碰
    onTouchPanelStart(event) {
        //双指操作部分
        let touches = event.getTouches();
        if (touches.length == 1) {
            // 一根手指是移动，这里不用写任何代码     
            let node = pg.view.find(this, 'layout_game/show_area');
            this.nodeStartPos = cc.v2(node);
        } else if (touches.length == 2) {
            this.startPos1 = this.node.convertToNodeSpaceAR(touches[0].getLocation());
            this.startPos2 = this.node.convertToNodeSpaceAR(touches[1].getLocation());
            this.pointsDis = this.startPos1.sub(this.startPos2).mag();
        }
    }
    scale: number;
    lastMove: cc.Vec2;
    nodeStartPos: cc.Vec2;
    touchTwo: boolean;
    // 手指移动 【放大/缩小】
    onTouchPanelMove(event) {
        let touches = event.getTouches();
        if (touches.length == 1) {// 单指位移
            if (this.touchTwo) return;
            let startPos = touches[0].getStartLocation()
            let nowPos = touches[0].getLocation()
            let movePos = cc.v2(nowPos.x - startPos.x, nowPos.y - startPos.y);
            let targetPos = cc.v2(movePos.x + this.nodeStartPos.x, movePos.y + this.nodeStartPos.y)
            this.updateAreaPosition(targetPos);
        } else if (touches.length == 2) {//双指缩放
            this.touchTwo = true;
            // 两根手指是缩放
            let touchPoint1 = this.node.convertToNodeSpaceAR(touches[0].getLocation());
            let touchPoint2 = this.node.convertToNodeSpaceAR(touches[1].getLocation());
            let newPointsDis = touchPoint1.sub(touchPoint2).mag();

            if (!this.pointsDis)        // 该行代码针对安卓手机
                this.pointsDis = 0;

            // 表明两根手指在往外划
            if (newPointsDis > this.pointsDis) {
                this.pointsDis = newPointsDis;
                this.scale += 0.05;
            }
            else if (newPointsDis < this.pointsDis) {
                this.pointsDis = newPointsDis;
                this.scale -= 0.05;
            }
            //执行缩放程序
            this.updateAreaScale(this.scale);
        }
    }
    // 触摸结束最后
    onTouchPanelEnd(event) {
        // 缩放过小，自动回弹
        if (this.scale <= 1) {
            this.scale = 1;
            this.updateAreaPosition();
            this.updateAreaScale();
        }
        // 回归触摸状态
        this.scheduleOnce(() => {
            this.touchTwo = false;
        }, 0.1)
    }
    // 更新显示区域和触摸区域的回弹
    updateAreaScale(scale = 1) {
        let show_area = pg.view.find(this, 'layout_game/show_area');
        let touch_area = pg.view.find(this, 'layout_game/touch_area');
        show_area.scale = scale;
        touch_area.scale = scale;
    }
    // 更新显示区域和触摸区域的重置 【此处有特殊的pos计算内容】
    updateAreaPosition(position = cc.v2(0, 0)) {
        let show_area = pg.view.find(this, 'layout_game/show_area');
        let touch_area = pg.view.find(this, 'layout_game/touch_area');
        show_area.x = position.x;
        show_area.y = position.y;
        touch_area.x = position.x - 643.196;
        touch_area.y = position.y + 476.596;
    }

    // 更新按钮及面板状态
    updateDoubleBtns() {
        let btns = pg.view.find(this, 'btns');
        pg.view.visible(pg.view.find(btns, 'btn_double_0'), !this.openDouble);
        pg.view.visible(pg.view.find(btns, 'btn_double_1'), this.openDouble);
        pg.view.visible(pg.view.find(btns, 'panel_double'), this.openDouble);
    }

    //--------------------------------------UPDATE--------------------------------
    update(dt) {
        let btns = pg.view.find(this, 'btns');

        pg.view.visible(pg.view.find(btns, 'btn_pre_1'), Game.getIns().hasPre());
        pg.view.visible(pg.view.find(btns, 'btn_next_1'), Game.getIns().hasNext());

        pg.view.visible(pg.view.find(btns, 'btn_play_0'), !this.openPlay);
        pg.view.visible(pg.view.find(btns, 'btn_play_1'), this.openPlay);
        pg.view.visible(pg.view.find(btns, 'btn_play_2'), this.openPlay && !this.pauseing);

        this.updateDoubleBtns();

        pg.view.visible(pg.view.find(btns, 'btn_single_0'), !this.openSingle);
        pg.view.visible(pg.view.find(btns, 'btn_single_1'), this.openSingle);

        let touch_area = pg.view.find(this, 'layout_game/touch_area');
        pg.view.visible(touch_area, this.openShowVoice);
        touch_area.children.forEach(node => {
            pg.view.visible(pg.view.find(node, 'wave'), this.openSingle)
        })

    }
    private currentTouchAreas: Array<cc.Node>;
    updateTouch() {
        let question = Game.getIns().getCurrentPage();
        //触摸区域
        let pos = question.pointsArr;
        let touch_area = pg.view.find(this, 'layout_game/touch_area');
        touch_area.removeAllChildren();
        this.currentTouchAreas = [];
        pos.forEach((li, idx) => {
            let item = cc.instantiate(this.card_node);
            touch_area.addChild(item);
            let com = item.getComponent('hitItem')
            com.initWithData(li)
            item.data = li;
            item.on(cc.Node.EventType.TOUCH_END, this.onItem, this);
            this.currentTouchAreas.push(item);
        })
    }
    updateImage(node, data) {
        node.active = true;
        let pic = pg.view.find(node, 'mask/bezier/page')
        let url = data.bgItem.url
        pg.load.loadNetImg(url).then((texture: cc.Texture2D) => {
            pic.getComponent('bezier-render').textureList[0] = texture
            pic.getComponent('bezier-render').init();
        })
    }
    updateTips(msg) {
        let tips = pg.view.find(this, 'tips');
        let label = pg.view.find(tips, 'label');
        pg.view.setString(label, msg)
        tips.active = true;
        tips.opacity = 255;
        cc.tween(tips).delay(1).to(0.3, { opacity: 0 }).call(() => { tips.active = false }).start();
    }
    private autoRoll: Function;
    updateRoll(totalTime) {
        let btn_play_roll = pg.view.find(this, 'btns/btn_play_roll');
        btn_play_roll.active = true;
        btn_play_roll.getComponent(cc.ProgressBar).progress = 0;
        // btn_play_roll.getComponent(cc.Sprite).fillRange = 0;
        let partTime = 0.03;
        // 需要一个真实的进度。  也就是当前时间占用totalTime的进度
        let lastTime = new Date().getTime();
        let pauseTime = null;
        this.autoRoll = () => {
            if (this.pauseing) {
                if (!pauseTime) {
                    pauseTime = new Date().getTime();
                }
                return;
            }
            let nowTime = new Date().getTime();
            if (pauseTime) {
                let subTime = nowTime - pauseTime;
                lastTime += subTime;
                pauseTime = null;
                console.log('subTime', subTime);
                console.log('lastTime', lastTime);
            }
            let perTime = (nowTime - lastTime) / 1000;
            let targetPercent = perTime / totalTime;
            if (targetPercent > 1) {
                targetPercent = 1;
                btn_play_roll.active = false;
                this.unschedule(this.autoRoll);
            }
            btn_play_roll.getComponent(cc.ProgressBar).progress = targetPercent;
        }
        this.schedule(this.autoRoll, partTime)
    }
    stopRoll() {
        this.unschedule(this.autoRoll);
        let btn_play_roll = pg.view.find(this, 'btns/btn_play_roll');
        btn_play_roll.active = false;
        // btn_play_roll.getComponent(cc.Sprite).fillRange = 0;
        btn_play_roll.getComponent(cc.ProgressBar).progress = 0;
    }
    //--------------------------------------BTNS--------------------------------
    onTouchBtnNext() {
        this.onStopAllAudio();
        this.updateAreaScale(1);
        this.updateAreaPosition(cc.v2(0, 0));
        this.playLocalAudio('page');
        pg.event.emit('page_to_left', Game.getIns().getCurrentPageNum());
        Game.getIns().addPage();
        this.updateTouch();
        this.hideDouble();
        this.openSingle = false;
        // this.onPlayAllAudio();
    }
    onTouchBtnPre() {
        this.onStopAllAudio();
        Game.getIns().subPage();
        this.updateAreaScale(1);
        this.updateAreaPosition(cc.v2(0, 0));
        this.playLocalAudio('page');
        pg.event.emit('page_to_right', Game.getIns().getCurrentPageNum());
        this.updateTouch();
        this.hideDouble();
        this.openSingle = false;
        // this.onPlayAllAudio();
    }
    onItem(e) {
        if (this.openPlay) return;
        if (!this.openSingle) return;
        this.readCount++;
        this.onStopAudio();
        this.onPlayAudio(e);
    }
    private currentPlay: { audioId, data, item };
    onPlayAudio(e) {
        return new Promise((resolve, reject) => {
            //
            let item = e.target;
            let data = e.target.data;
            this.currentPlay = { audioId: null, data, item }
            //播放音频
            let item_laba = pg.view.find(item, 'item_laba');
            item_laba.x = -item.width / 2;
            item_laba.y = -item.height / 2;
            pg.view.visible(pg.view.find(item, 'wave/ani'), false)
            pg.view.visible(pg.view.find(item, 'item_laba'), true)
            pg.audio.playAudioByUrl(data.audio, () => {
                if (data.audio != this.currentPlay.data.audio) return;
                pg.view.visible(pg.view.find(item, 'wave/ani'), true)
                pg.view.visible(pg.view.find(item, 'item_laba'), false)
                this.currentPlay = null;
                this.scheduleOnce(() => {
                    resolve('');
                }, 2)
            }, (audioId) => {
                if (data.audio != this.currentPlay.data.audio) return;
                this.currentPlay.audioId = audioId;
            })
        });
    }
    onStopAudio() {
        if (this.currentPlay) {
            cc.audioEngine.stopEffect(this.currentPlay.audioId)
            let item = this.currentPlay.item
            pg.view.visible(pg.view.find(item, 'wave/ani'), true)
            pg.view.visible(pg.view.find(item, 'item_laba'), false)
        }
    }
    onTouchBtnSingle() {
        this.onStopAllAudio();
        //允许点击操作
        this.openSingle = !this.openSingle;
        if (this.openSingle) {
            this.openShowVoice = true;
            this.hideDouble();
            this.updateAreaScale();
            this.updateAreaPosition(cc.v2(0, 0));
            this.updateTips('开启课文点读模式');
        } else {
            this.openShowVoice = false;
        }
    }
    private pauseing: boolean;
    async onTouchBtnPlay() {
        if (this.openPlay) {
            this.readCount++;
            this.pauseing = !this.pauseing;
            if (this.pauseing) {
                cc.audioEngine.pauseAllEffects();
            } else {
                cc.audioEngine.resumeAllEffects();
            }
        } else {
            this.updateTips('开始连续播放音频');
            this.hideDouble();
            this.updateAreaScale();
            this.updateAreaPosition(cc.v2(0, 0));
            this.openSingle = false;
            this.onStopAllAudio();
            this.onPlayAllAudio();
        }
    }
    private lastTime: number;
    onPlayAllAudio() {
        return new Promise(async (resolve, reject) => {
            this.openPlay = true;
            this.pauseing = false;
            let time = new Date().getTime();
            this.lastTime = time;
            this.openShowVoice = true;
            let totalTime = 0;
            for (let i = 0; i < this.currentTouchAreas.length; i++) {
                let node = this.currentTouchAreas[i];
                if (!node) return;
                let data = node.data;
                //音频文件加载
                let audioClip: cc.AudioClip = await pg.audio.getAudioClip(data.audio);
                totalTime += audioClip.duration;
                totalTime += 2;
                if (!this.lastTime || this.lastTime != time) return;
            }
            this.updateRoll(totalTime);
            for (let i = 0; i < this.currentTouchAreas.length; i++) {
                let node = this.currentTouchAreas[i];
                if (!node) continue;
                //音频文件加载
                await this.onPlayAudio({ target: node });
                if (!this.lastTime || this.lastTime != time) return;
            }
            this.openShowVoice = false;
            resolve('');
        });
    }
    onStopAllAudio() {
        this.openPlay = false;
        //执行中断程序
        this.lastTime = null;
        this.onStopAudio();
        this.stopRoll();
    }


















    playLocalAudio(audioName) {
        const audio = cc.find(`Canvas/res/audio/${audioName}`).getComponent(cc.AudioSource);
        return new Promise((resolve, reject) => {
            const id = cc.audioEngine.playEffect(audio.clip, false);
            cc.audioEngine.setFinishCallback(id, () => { resolve(id); });
        })
    }
}


