import { Scene } from "../../module/views/Scene";
import * as Matter from "matter-js";
import Role from "./components/Role";
import { RES } from "../../module/RES";
import AddProp from "./components/AddProp";
import ObstacleProp from "./components/ObstacleProp";
import MapItem from "./components/MapItem";
import { getWebData, WebNetName, sendWebNet, LOG_TYPE } from "../webNet";
import { showPanel, showToast, changeScene } from "../../module/ctrls";
import { GuidePanel } from "../panels/GuidePanel";
import { StartScene } from "./StartScene";
import { SuccessPanel } from "../panels/SuccessPanel";
import { FailPanel } from "../panels/FailPanel";
import { duiba_md5 } from "../../module/tools/security";
import { Tools } from "../Tools";
import { playAllSound } from "../common/SoundWeb";
import { layers } from "../../module/views/layers";
import UI from "../UI";
import { allWords } from "../contant";
import { getUrlParams } from "../../module/web/webTools";
import { GDispatcher } from "../Main";

export class GameScene extends Scene {
    get groupNames() { return ["GameScene"] };
    get skinName() { return "GameScene" };

    bg: FYGE.Sprite;
    left;
    right;
    cdbg: FYGE.Sprite;
    reset;

    time = Tools.configInfo.time;
    wordList = this.getWordList(); // 待随机出现的列表
    wordLen = this.getWordList().length; // 需要收集字体的个数
    collectList: any = []; // 已收集列表
    public static instance: GameScene;
    initUi() {

    }
    async start(data) {
        super.start();
        GameScene.instance = this
        showPanel(GuidePanel);

        this.reset.addEventListener(FYGE.MouseEvent.CLICK, () => {
            this.btnDelay(this.reset)
            this.onReset()
        }, this)

        // 左右按钮
        this.left = new FYGE.SvgaAni(await RES.getResAsync("left.svga"))
        this.left = this.addChild(this.left)
        this.left.position.set(8, 979);
        this.left.startAniRange(1, 1, 1);

        this.right = new FYGE.SvgaAni(await RES.getResAsync("right.svga"))
        this.right = this.addChild(this.right)
        this.right.position.set(524, 979);
        this.right.startAniRange(1, 1, 1);

        this.left.addEventListener(FYGE.MouseEvent.CLICK, () => {
            this.left.startAniRange(1, undefined, 1, () => { })
            this._role.leftMove()
        })
        this.right.addEventListener(FYGE.MouseEvent.CLICK, () => {
            this.right.startAniRange(1, undefined, 1, () => { })
            this._role.rightMove()
        })

        // 倒计时
        this.cdbg = UI.Sp(this, "cdbg.png", 280, 330)
        this.cdUIRender(this.time)

        // 物理引擎
        this.createPhyWorld()
        this.bgCon = this.addChild(new FYGE.Container());
        this.setChildIndex(this.bgCon, 1)
        this.initMap();

        // // TODO_wyx
        // this.upDateInfo()
    }
    // 数据重置
    onReset() {
        changeScene(StartScene)
    }
    getWordList() {
        let dataInfo = getWebData(WebNetName.indexInfo).data.dataInfo;
        let hasWordList: any = [];
        let noWordList: any = [];
        dataInfo.forEach(item => {
            if (item.context) {
                hasWordList = hasWordList.concat(item.context.split(""))
            }
        })
        allWords.forEach(item => {
            if (!hasWordList.includes(item) && !noWordList.includes(item)) {
                noWordList.push(item)
            }
        })
        return noWordList
    }

    score;
    upDateInfo() {
        this.time = Tools.configInfo.time;
        this.cdUIRender(this.time)
        this.startGame()
        this.countDown(this.time)
    }
    countDown(time) {
        if (this.timer) {
            clearTimeout(this.timer);
        }
        this.timer = setTimeout(() => {
            if (this.time <= 0) {
                clearTimeout(this.timer);
                this.composites.remove(this.world, this._role.phyBody);
                this.gameOver()
                return
            }
            this.time = this.time - 1;
            this.cdUIRender(this.time)
            this.countDown(this.time)
        }, 1000)
    }

    cdUIRender(num = 60) {
        // 先清除所有节点
        this.cdbg.removeChildren();
        let str = num + 's';
        let arr = str.split("");
        let startPos = (192 - (30 * arr.length)) / 2
        arr.forEach((item, index) => {
            UI.Sp(this.cdbg, `num_${item}.png`, startPos + (index * 30), 46)
        })
    }

    startGame() {
        this.addRole();
        this.addEventListener(FYGE.Event.ENTER_FRAME, this.onFarm, this);
    }
    _role; //人物
    bgCon; //背景移动

    addRole() {
        let offset = (1624 - this.stage.viewRect.height) / 2;
        let role = this._role = new Role({
            stageY: this.stage.viewRect.y,
        });
        role.fx = 339;
        role.fy = 980 - offset;
        this.bgCon.addChild(role);
        this.composites.add(this.world, [this._role.phyBody]);
    }
    engine; // matter引擎初始化
    composites;
    world;
    runner;
    ground;
    private createPhyWorld() {
        const { Engine, Render, Runner, Composite, Bodies, World, Composites } = Matter;
        this.engine = Engine.create(
            {
                enableSleeping: true
            }
        );
        this.world = this.engine.world;
        this.engine.gravity.y = 0.5;

        /** 真正运行 */
        this.runner = Runner.create();
        Runner.run(this.runner, this.engine);
        // @ts-ignore
        this.composites = Composite;

        Matter.Events.on(this.engine, "collisionStart", this.onCollisionStart.bind(this));
        Matter.Events.on(this.engine, "tick", this.onCollisionTick.bind(this));
        // 创建一个渲染器
        // const render = Render.create({
        //     // element: document.body,
        //     canvas: document.getElementById("renderCanvas"),
        //     engine: this.engine,
        //     options: {
        //         width: document.body.clientWidth,
        //         height: document.body.clientHeight,
        //         pixelRatio: window.devicePixelRatio, // 设置像素比
        //         background: "rgba(255,255,255,0.3)", // 全局渲染模式时背景色
        //         wireframeBackground: "rgba(255,255,255,0.3)", // 线框模式时背景色
        //         hasBounds: false,
        //         wireframes: false, // 线框模式
        //         showSleeping: true, // 刚体睡眠状态
        //         showDebug: false, // Debug 信息
        //         showBroadphase: false, // 粗测阶段
        //         showBounds: true, // 刚体的界限
        //         showVelocity: false, // 移动刚体时速度
        //         showCollisions: false, // 刚体碰撞点
        //         showSeparations: false, // 刚体分离
        //         showAxes: false, // 刚体轴线
        //         showPositions: true, // 刚体位置
        //         showAngleIndicator: false, // 刚体转角指示
        //         showIds: true, // 显示每个刚体的 ID
        //         showVertexNumbers: false, // 刚体顶点数
        //         showConvexHulls: false, // 刚体凸包点
        //         showInternalEdges: false, // 刚体内部边界
        //         showMousePosition: false, // 鼠标约束线
        //     },
        // });
        // Render.run(render);
    }
    onCollisionTick(e) {
    }
    lastTime = 0
    onCollisionStart(e) {
        let pairs = e.pairs;
        pairs.map((p) => {
            // ip 与 云朵 碰撞, 进行人物跳跃
            if ((p.bodyA.objType == "cloud" && p.bodyB == this._role.phyBody) || (p.bodyB.objType == "cloud" && p.bodyA == this._role.phyBody)) {
                if (this.engine.timing.timestamp - this.lastTime >= 400) {
                    this._role.jump()
                    this.lastTime = this.engine.timing.timestamp;
                }

            }

            // ip 与 文字 碰撞, 进行收集文字
            if ((p.bodyA.objType == "word" && p.bodyB == this._role.phyBody) || (p.bodyB.objType == "word" && p.bodyA == this._role.phyBody)) {
                if (p.bodyA.objType == "word") {
                    if (!this.collectList.includes(p.bodyA.wordTx)) {
                        this.collectList.push(p.bodyA.wordTx);
                        let _i = this.wordList.indexOf(p.bodyA.wordTx);
                        if (_i > -1) {
                            this.wordList.splice(_i, 1)
                        }
                    }
                    this.composites.remove(this.world, p.bodyA);
                    setTimeout(() => {
                        this.bgCon.removeChild(p.bodyA.nodeTx);
                    }, 100)
                }
                if (p.bodyB.objType == "word") {
                    if (!this.collectList.includes(p.bodyB.wordTx)) {
                        this.collectList.push(p.bodyB.wordTx);
                        let _i = this.wordList.indexOf(p.bodyB.wordTx);
                        if (_i > -1) {
                            this.wordList.splice(_i, 1)
                        }
                    }
                    this.composites.remove(this.world, p.bodyB);
                    setTimeout(() => {
                        this.bgCon.removeChild(p.bodyB.nodeTx);
                    }, 100)
                }
            }
        })
    }
    initMap() {
        let stageHeight = this.stage.stageHeight;
        // 循环多建几行
        for (let i = 0; i < 10; i++) {
            if (i == 0) {
                this.createLineItem(stageHeight - (260 * (i + 1)), 10, 4, 15);
            } else {
                this.createLineItem(stageHeight - (260 * (i + 1)));
            }
        }
    }
    mapList = [];
    createLineItem(h, _sx?: number, _rLen?:number, _space?: number) {
        let sx = _sx || Math.floor(Math.random() * 300 - 100); // 初始第一朵云的坐标
        let rLen = _rLen || Math.floor(Math.random() * 4 + 2); // 每一行随机出现几朵云
        let space = _space || Math.floor(Math.random() * 80); // 增加一点随机间距
        const offsetY = this.stage.viewRect.y;
        let cloudLi = [];
        for (let i = 0; i < rLen; i++) {
            let mapItem = new MapItem({
                fx: sx + i * 222 + i * (space + 20),
                fy: h,
                stageY: offsetY
            });
            this.bgCon.addChildAt(mapItem, 0);
            this.composites.add(this.world, [mapItem.phyBody]);
            let len = this.wordList.length
            let randomIndex;
            if (len > 0) {
                randomIndex = Math.floor(Math.random() * len);
            }
            // 添加文字
            let addProp = new AddProp({
                fx: sx + i * 222 + i * (space + 20) + 46,
                fy: h - 70,
                stageY: offsetY,
                wordTx: len == 0 ? '' : this.wordList[randomIndex]
            });
            this.bgCon.addChildAt(addProp, 1)
            this.composites.add(this.world, [addProp.phyBody]);
            cloudLi.push([mapItem, addProp])
        }
        this.mapList.push(cloudLi)
    }
    timer = null;
    isFall;
    onFarm() {
        // 检测收集的字
        if (this.collectList.length >= this.wordLen) {
            // 游戏结束
            this.composites.remove(this.world, this._role.phyBody);
            clearTimeout(this.timer);
            this.gameOver();
            return
        }
        let roleY = this._role.y + this.bgCon.y;
        // 移动容器的位置
        if (roleY < 600) {
            this.moveMap(600 - roleY)
        }

        // 检测最后一行, 然后移除节点
        let lastLine = this.mapList[0],
            lastItem = lastLine[0][0]; // 云
        if (lastItem.y + this.bgCon.y > this.stage.stageHeight + 120) {
            lastLine.forEach(item => {
                item.forEach(_item => {
                    this.composites.remove(this.world, _item.phyBody);
                    _item.destroy();
                    this.bgCon.removeChild(_item);
                })
            })
            this.mapList.shift()
        }

        // 检测第一行是否要插入数据
        let firstLine = this.mapList[this.mapList.length - 1],
            firstItem = firstLine[0][0];
        if (firstItem.y + this.bgCon.y > -100) {
            this.createLineItem(firstItem.y - 260)
        }

        if (this._role.y >= -(this.bgCon.y - 1624)) {
            console.log("人物出了舒适圈", this.mapList)
            this.isFall = true
            let toItem = this.mapList[0][1]
            console.log(lastItem.fx, lastItem.fy)
            this._role.fx = lastItem.fx + 60
            this._role.fy = lastItem.fy - 200
        }

    }
    moveMap(y) {
        if (this.isFall) return
        this.bgCon.y = this.bgCon.y + y;
    }

    removeWorld() {
        this.composites.clear(this.world)
        this.mapList = [];
    }
    getDataArr() {
        console.log('this.collectList', this.collectList)
        let arr = ["闲看晴云自卷舒", "静水流深", "云卷舒", "心无意", "自在休闲"];
        let tempData = []
        arr.forEach((item, index) => {
            let words = [];
            item.split("").forEach(val => {
                if (this.collectList.includes(val)) {
                    if (words.indexOf(val) == -1) {
                        words.push(val)
                    }
                }
            })
            tempData.push({
                num: index + 1,
                context: words.join(',')
            })
        })
        return tempData
    }
    //游戏结束
    async gameOver() {
        if (this._role) {
            this._role.jumpSvga.visible = false;
            this._role.downSvga.visible = true;
        }
        this.removeEventListener(FYGE.Event.ENTER_FRAME, this.onFarm, this);
        this.removeWorld()
        // 接口提交
        let activityId = getUrlParams('activityId');
        let startId = getWebData(WebNetName.startGame).data.startId;
        let timestamp = new Date().getTime();
        let type = 3
        let sign = duiba_md5(String(activityId) + String(timestamp) + String(startId) + String(type) + 'posf3usrjjnd9sd4w21ln3p');
        let dataArr = this.getDataArr();
        const { success, data, desc } = await sendWebNet(WebNetName.submitGame, {
            activityId,
            type,
            startId,
            timestamp,
            sign,
            longitude: Tools.configInfo.longitude,
            latitude: Tools.configInfo.latitude,
            data: dataArr
        })
        if (success) {
            GDispatcher.dispatchEvent("openGameEnd", {
                point: data.point || 0
            });
        } else {
            showToast(desc || "网络开小差了，稍后再试")
        }
    }
    closeGame() {
        changeScene(StartScene)
    }
    initEvents() {
        super.initEvents();
        GDispatcher.addEventListener("closeGame", this.closeGame, this);
    }
    removeEvents() {
        super.removeEvents();
        clearTimeout(this.timer);
        GDispatcher.removeEventListener("closeGame", this.closeGame, this);
    }
}

