import { asyncDelay, onHomeworkFinish } from "../script/util";
import { MyCocosSceneComponent } from "../script/MyCocosSceneComponent";
import pg from "./pg";
import map from "./map";

const { ccclass, property } = cc._decorator;
enum CELLTYPE {
    SPEAK = 1,
    MOVE_ADD = 2,
    ROLL_AGAIN = 3,
    DELAY_TIME = 4,
    JUMP_ROLL = 5,
    WIN = 100,
}
@ccclass
export default class SceneComponent extends MyCocosSceneComponent {

    addPreloadImage() {
        // TODO 根据自己的配置预加载图片资源
        this._imageResList.push({ url: this.data.pic_url });
        this._imageResList.push({ url: this.data.pic_url_2 });
    }

    addPreloadAudio() {
        // TODO 根据自己的配置预加载音频资源
        this._audioResList.push({ url: this.data.audio_url });
    }

    addPreloadAnima() {

    }

    onLoadEnd() {
        // TODO 加载完成后的逻辑写在这里, 下面的代码仅供参考
        this.initData();
        this.initView();
        this.initEvent();
    }

    _cantouch = null;
    initData() {
        // 所有全局变量 默认都是null 
        this._cantouch = true;
    }
    //开发流程
    //1.start状态
    //2.开局效果
    //3.骰子动效，stop效果。
    //4.星星位移。
    //--游戏开始就计算好后续的所有点数数组。
    //--骰子及位移点数等添加到一个数组中，每次需要获取当前点和目标点时进行实时获取。
    //--出现错误反向退回。
    //--位移停止后触发目的地内容。
    //5.触发目的地道具效果。
    //--如各类道具，进行分类。统一调用一个方法输入，给予id
    //--如：终点。可触发终点效果。
    //--如：语音。触发语音效果。
    //--如：加速。触发位移效果。
    //6.语音录音部分。
    //--动画组件，start  end。
    //7.机器人骰子及自动进程。
    //--机器人难度处理，游戏开始就计算好后续的所有点数数组。
    //--调用通用的内容进行位移。
    //8.结算胜负
    //9.重新开始
    initView() {
        this.initTouzi();
        this.initChess();
    }
    initEvent() {
        pg.event.on("game_start", () => { this.onGameStart() })

        pg.event.on("speak_success", () => { this.onSpeakScueess() });
        pg.event.on("speak_fail", () => { this.onSpeakFail() });
    }
    //-----------------------------流程------------------------------
    private playerPoint: number;//
    private robotPoint: number;//
    private turnRobot: boolean;//当前是谁操作
    onGameStart() {
        this.playerPoint = 0;
        this.robotPoint = 0;
        this.turnRobot = Math.random() < 0.5;
        this.initChess();
        setTimeout(() => {
            this.startTouzi();
        }, 2100);
    }
    onSpeakScueess() {
        //执行后续的动作。
        this.turnNext();
    }
    onSpeakFail() {
        //回退到最后一个位置
        let cell = map[this.playerPoint];
        this.jumpChess(cell, this.lastPointId).then(() => {

            this.turnNext();
        })
    }
    turnNext() {
        this.turnRobot = !this.turnRobot;
        this.startTouzi();
    }
    //-----------------------------CHESS-------------------------------
    private chessPlayer: cc.Node;
    private chessRobot: cc.Node;
    initChess() {
        //初始化棋子
        this.chessPlayer = pg.view.find(this, "chess/chess_player");
        this.chessRobot = pg.view.find(this, "chess/chess_robot");
        let point = map[0];
        this.chessPlayer.x = Number(point.yellow_x);
        this.chessPlayer.y = Number(point.yellow_y);
        this.chessRobot.x = Number(point.blue_x);
        this.chessRobot.y = Number(point.blue_y);
    }
    getMovePoints(now, runNum) {
        let points = [];
        for (let i = now; i <= now + runNum; i++) {
            let point = map[i];
            if (!point) break;
            points.push(point);
        }
        return points;
    }
    moveChess(runNum) {
        return new Promise((resolve, reject) => {
            this.runNum = runNum;
            if (this.turnRobot) {
                let points = this.getMovePoints(this.robotPoint, runNum);
                console.log(points);
                this.chessRobot.getComponent("chess").run(points).then(() => {
                    this.robotPoint += runNum;
                    resolve('');
                })
            } else {
                let points = this.getMovePoints(this.playerPoint, runNum);
                console.log(points);
                this.chessPlayer.getComponent("chess").run(points).then(() => {
                    this.playerPoint += runNum;
                    resolve('');
                })
            }
        });
    }
    jumpChess(cell, jumpId) {
        return new Promise((resolve, reject) => {
            let jumpCell = map[jumpId - 1];
            let points = [cell, jumpCell];
            if (this.turnRobot) {
                this.chessRobot.getComponent("chess").run(points).then(() => {
                    this.robotPoint = Number(jumpCell.id) - 1;
                    resolve('');
                })
            } else {
                this.chessPlayer.getComponent("chess").run(points).then(() => {
                    this.playerPoint = Number(jumpCell.id) - 1;
                    resolve('');
                })
            }
        });
    }
    private runNum: number;
    checkCell() {
        if (this.turnRobot) {
            let cell = map[this.robotPoint];
            let val = cell.value;
            let type = Number(cell.type);
            switch (type) {
                case CELLTYPE.MOVE_ADD:
                    this.moveChess(Number(val)).then(() => {
                        this.checkCell();
                    })
                    break;
                case CELLTYPE.ROLL_AGAIN:
                    this.turnRobot = !this.turnRobot;
                    this.turnNext();
                    break;
                case CELLTYPE.JUMP_ROLL:
                    this.jumpChess(cell, Number(val)).then(() => {
                        this.checkCell();
                    })
                    break;
                case CELLTYPE.WIN:
                    this.gameOver();
                    break;
                default:
                    this.turnNext();
                    break;
            }
            return
        }
        setTimeout(() => {
            let cell = map[this.playerPoint];
            let val = cell.value;
            let type = Number(cell.type);
            switch (type) {
                case CELLTYPE.SPEAK:
                    pg.event.emit("speak_open", cell)
                    break;
                case CELLTYPE.DELAY_TIME:
                    setTimeout(() => {
                        this.turnNext();
                    }, 5000);
                    break;
                case CELLTYPE.MOVE_ADD:
                    this.moveChess(Number(val)).then(() => {
                        this.checkCell();
                    })
                    break;
                case CELLTYPE.ROLL_AGAIN:
                    this.turnRobot = !this.turnRobot;
                    this.turnNext();
                    break;
                case CELLTYPE.JUMP_ROLL:
                    this.jumpChess(cell, Number(val)).then(() => {
                        this.checkCell();
                    })
                    break;
                case CELLTYPE.WIN:
                    this.gameOver();
                    break;
                default:
                    this.turnNext();
                    break;
            }
        }, 100);
    }
    //-----------------------------TOUZI-------------------------------
    initTouzi() {
        let touzi_ani = pg.view.find(this, "touzi_ani");
        let btn_stop = pg.view.find(touzi_ani, "btn_stop");
        pg.view.touchOn(btn_stop, this.onTouchStop, this);
    }
    onTouchStop() {
        if (this.turnRobot) return;
        this.stopTouzi();
    }
    lastPointId: number;
    stopTouzi(runNum = 0) {
        pg.audio.stopAudio(this.touziAudio);
        let touzi_ani = pg.view.find(this, "touzi_ani");
        let icon = pg.view.find(touzi_ani, "icon");
        let touzi = icon.getComponent("touzi");
        let hand = pg.view.find(touzi_ani, "hand");
        let btn_stop = pg.view.find(touzi_ani, "btn_stop");
        btn_stop.active = false;
        this.lastPointId = this.playerPoint + 1;
        if (!runNum) {
            runNum = 1 + Math.floor(Math.random() * 6);
            if (this.turnRobot) runNum = 1 + Math.floor(Math.random() * 5);
        }
        hand.active = false;
        clearTimeout(this.stopHandTimer);
        touzi.stopAni(runNum).then(() => {
            touzi_ani.active = false;
            pg.event.emit("player_point_update", { isRobot: this.turnRobot, num: runNum });
            this.moveChess(runNum).then(() => {
                this.checkCell();
            })
        })
    }
    private stopHandTimer: number;
    private touziAudio: number;
    startTouzi() {
        let touzi_ani = pg.view.find(this, "touzi_ani");
        let icon = pg.view.find(touzi_ani, "icon");
        let touzi = icon.getComponent("touzi");
        let hand = pg.view.find(touzi_ani, "hand");
        let btn_stop = pg.view.find(touzi_ani, "btn_stop");
        btn_stop.active = true;
        touzi_ani.active = true;
        touzi.startAni();
        if (this.turnRobot) {
            setTimeout(() => {
                this.stopTouzi();
            }, 300 + Math.random() * 200);
        } else {
            this.stopHandTimer = setTimeout(() => {
                hand.active = true;
            }, 5000);
        }
        pg.hw.playLocalAudio("touzi", true).then((id: number) => {
            this.touziAudio = id;
        })
    }
    //----------------------------OVER-------------------
    gameOver() {
        let state = pg.view.find(this, "state");
        let bg_win = pg.view.find(state, "bg_win");
        let bg_lose = pg.view.find(state, "bg_lose");
        pg.view.visible(state, true);
        if (this.playerPoint > this.robotPoint) {
            pg.view.visible(bg_win, true);
            pg.view.visible(bg_lose, false);
            pg.hw.playLocalAudio("flower");
        } else {
            pg.view.visible(bg_win, false);
            pg.view.visible(bg_lose, true);
        }
        setTimeout(() => {
            pg.view.visible(bg_win, false);
            pg.view.visible(bg_lose, false);
            pg.event.emit("game_over");
        }, 5000);
        // onHomeworkFinish最后需要添加作业完成
        onHomeworkFinish();
    }
    //-----------------------------TOOL-------------------------------
    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);
            });
        })
    }
}
