import { PropPanel } from './../../panels/PropPanel';
import { QuitPanel } from './../../panels/QuitPanel';
import { PropOutPanel } from './../../panels/PropOutPanel';
import { showWaiting, hideWaiting } from './../../../module/ctrls/waitingCtrl';
import { PropType } from './../../commonNet';
import { UnlockPanel } from './../../panels/UnlockPanel';
import { playSound } from './../../../module/ctrls/soundCtrl';
import { FrameAni } from './../../../engine/2d/ui/FrameAni';
import { MovieClip } from './../../../engine/2d/svga/MovieClip';
import { Shape } from './../../../engine/2d/graphics/Shape';
import { noBlockLeft, noBlockRight, noBlockTop, noBlockBottom, checkMusic } from './Check';
import { GDispatcher } from './../../../engine/2d/events/GDispatcher';
import { Button } from './../../../engine/2d/ui/Button';
import { GameEle } from './GameEle';
import { layers } from './../../../module/views/layers';
import { TextField } from '../../../engine/2d/text/TextField';
import { MouseEvent } from '../../../engine/2d/events/MouseEvent';
import { Scene } from '../../../module/views/Scene';
import { Container, Sprite } from '../../../engine/2d/display';
import { Graphics } from '../../../engine/2d/graphics';
import Tween from '../../../engine/tween/Tween';
import { RES } from '../../../module/RES';
import { getTools, getSoundStatus, useTools } from '../../commonNet'
import PanelCtrl from '../../../module/ctrls/panelCtrl';
import { showPanel } from '../../../module/ctrls';
export class PlayScene extends Scene {
    get groupNames() { return ["playScene"] }

    gameData
    constructor(data) {
        super()
        this.gameData = data
    }

    start() {
        this.initUI()
        this.initEvents()


    }

    board: any[] = []
    containerPool = []

    _score = 0

    set score(value) {
        this._score = value
        this.dispatchEvent("updateScoreTxt")
    }

    get score() {
        return this._score
    }

    _unlockGrade = 2
    set unlockGrade(value) {
        this._unlockGrade = value
        this.unlockGradeTxt.text = this._unlockGrade + ""
    }
    get unlockGrade() {
        return this._unlockGrade
    }

    _isPlayMusic: boolean = false

    set isPlayMusic(value) {
        this._isPlayMusic = value
        if (this._isPlayMusic) {
            this.musicBtn.texture = RES.getRes("musicOn.png")
        } else {
            this.musicBtn.texture = RES.getRes("musicOff.png")
        }
    }

    get isPlayMusic() {
        return this._isPlayMusic
    }

    bg: Sprite
    goBackBtn: Button
    musicBtn: Button
    bombBtn: Button
    bombCountTxt: TextField
    exchangeBtn: Button
    exchangeCountTxt: TextField
    filterBtn: Button
    filterCountTxt: TextField
    scoreTxt: TextField
    unlockGradeTxt: TextField



    initUI() {
        this.y = -(1624 - layers.stageHeight) / 2;

        this.bg = new Sprite(RES.getRes('playBg.png'))
        this.bg.width = 750
        this.bg.height = 1624
        this.bg.x = 0
        this.bg.y = 0
        this.addChild(this.bg)

        this.scoreTxt = this.addChild(this.drawTxt(this.score, 210, 340, "#ffffff", 36)) as TextField
        this.addEventListener("updateScoreTxt", this.updateScoreTxt, this)
        this.score = 0

        this.unlockGradeTxt = this.addChild(this.drawTxt(this.unlockGrade, 520, 340, "#ffffff", 36)) as TextField

        this.exchangeBtn = new Button(RES.getRes('exchangeBtn.png'))
        this.exchangeBtn.y = 1280
        this.exchangeBtn.x = 115
        this.addChild(this.exchangeBtn)

        let exchangeBottom = new Sprite(RES.getRes("propBottom.png"))
        exchangeBottom.x = 90
        exchangeBottom.y = 0
        this.exchangeBtn.addChild(exchangeBottom)

        this.exchangeCountTxt = this.drawTxt(0, 105, 10, "#ffffff", 26)
        this.exchangeBtn.addChild(this.exchangeCountTxt)

        this.bombBtn = new Button(RES.getRes('bombBtn.png'))
        this.bombBtn.y = 1280
        this.bombBtn.x = 312
        this.addChild(this.bombBtn)

        let bombBottom = new Sprite(RES.getRes("propBottom.png"))
        bombBottom.x = 90
        bombBottom.y = 0
        this.bombBtn.addChild(bombBottom)

        this.bombCountTxt = this.drawTxt(0, 105, 10, "#ffffff", 26)
        this.bombBtn.addChild(this.bombCountTxt)

        this.filterBtn = new Button(RES.getRes('filterBtn.png'))
        this.filterBtn.y = 1280
        this.filterBtn.x = 510
        this.addChild(this.filterBtn)

        let filterBottom = new Sprite(RES.getRes("propBottom.png"))
        filterBottom.x = 90
        filterBottom.y = 0
        this.filterBtn.addChild(filterBottom)

        this.filterCountTxt = this.drawTxt(0, 105, 10, "#ffffff", 26)
        this.filterBtn.addChild(this.filterCountTxt)

        this.loadSvgas()

        for (let x = 0; x < 4; x++) {
            this.board[x] = []
            this.containerPool[x] = []
            let py = 596 + x * 136
            for (let y = 0; y < 4; y++) {
                let num = 0
                this.board[x][y] = num
                let px = 104 + y * 138
                let container = new Container();
                container.x = px
                container.y = py
                // container["idx"] = x + y + ""
                container['cx'] = x
                container['cy'] = y
                this.addChild(container);
                container.addChild(new GameEle(num))
                this.containerPool[x][y] = container
            }
        }

        this.goBackBtn = new Button(RES.getRes("goBackBtn.png"))
        this.goBackBtn.x = 0
        this.goBackBtn.y = 200
        this.addChild(this.goBackBtn)
        this.musicBtn = new Button(RES.getRes("musicOn.png"))
        this.musicBtn.x = 680
        this.musicBtn.y = 200
        this.addChild(this.musicBtn)

        this.exchangeTarget1 = new Sprite(RES.getRes("focusTips.png"))
        this.exchangeTarget2 = new Sprite(RES.getRes("focusTips.png"))


        if (!localStorage.getItem("game2048Guide")) {
            localStorage.setItem("game2048Guide", "true")
            this.board[1][0] = 2
            this.board[1][3] = 2
            this.renderBoard()
            this.initGuide()
        } else {
            this.generateOneElement()
            this.generateOneElement()
        }

        this.isPlayMusic = getSoundStatus()

        this.updateProp(this.gameData.bombCount, this.gameData.exchangeCount, this.gameData.netCount)
        this.unlockGrade = this.gameData.unlockGrade ? this.gameData.unlockGrade : 2

    }

    resetGame() {
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                this.board[x][y] = 0

            }
        }
        this.generateOneElement()
        this.generateOneElement()
        this.renderBoard()
        this.score = 0
    }

    createAniPool = []
    createArr = [4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]
    loadSvgas() {
        for (let i = 0; i < this.createArr.length; i++) {
            this.createAniPool[i] = RES.getRes("create" + this.createArr[i] + ".svga")
        }

    }

    guideMask
    initGuide() {
        this.guideMask = new Graphics();
        this.guideMask.mouseChildren = true
        this.guideMask.mouseEnable = true
        this.guideMask.beginFill(0x000000, 0.6);
        this.guideMask.moveTo(0, 0)
        this.guideMask.lineTo(750, 0)
        this.guideMask.lineTo(750, 586)
        this.guideMask.lineTo(94, 586)
        this.guideMask.lineTo(94, 1140)
        this.guideMask.lineTo(656, 1140)
        this.guideMask.lineTo(656, 586)
        this.guideMask.lineTo(750, 586)
        this.guideMask.lineTo(750, 1624)
        this.guideMask.lineTo(0, 1624)
        this.guideMask.lineTo(0, 0)
        this.guideMask.endFill();

        this.addChild(this.guideMask)

        let arrow = new Sprite(RES.getRes("guideArrow.png"))
        arrow.x = 500
        arrow.y = 900
        arrow.alpha = 0
        this.guideMask.addChild(arrow)

        Tween.get(arrow, { loop: true })
            .to({ x: 355, alpha: 1 }, 600)
            .wait(200)


        let finger = new Sprite(RES.getRes("guideFinger.png"))
        finger.x = 500
        finger.y = 900
        this.guideMask.addChild(finger)

        Tween.get(finger, { loop: true })
            .to({ x: 350 }, 500)
            .wait(300)

        let tips = this.drawTxt("滑动屏幕让2个相同食物碰撞", 250, 1000)
        this.guideMask.addChild(tips)
    }

    updateScoreTxt() {
        this.scoreTxt.text = this._score + ""
    }

    initEvents() {
        super.initEvents()
        this.addEventListener(MouseEvent.MOUSE_DOWN, this.onDown_this, this)
        GDispatcher.addEvent("updateProp", this.updateProp, this)
        this.exchangeBtn.addEventListener(MouseEvent.CLICK, this.onClick_exchangeBtn, this)
        this.bombBtn.addEventListener(MouseEvent.CLICK, this.onClick_bombBtn, this)
        this.filterBtn.addEventListener(MouseEvent.CLICK, this.onClick_filterBtn, this)
        this.musicBtn.addEventListener(MouseEvent.CLICK, this.onClick_musicBtn, this)
        this.goBackBtn.addEventListener(MouseEvent.CLICK, this.onClick_goBackBtn, this)
    }

    onClick_goBackBtn() {
        showPanel(QuitPanel, { grade: this.unlockGrade, score: this.score })
    }

    onClick_musicBtn() {
        this.isPlayMusic = !this.isPlayMusic
    }

    _bombCount: number = 0
    _exchangeCount: number = 0
    _netCount: number = 0

    set bombCount(value) {
        this._bombCount = value
        this.bombCountTxt.text = this._bombCount + ""
    }

    get bombCount() {
        return this._bombCount
    }

    set exchangeCount(value) {
        this._exchangeCount = value
        this.exchangeCountTxt.text = this._exchangeCount + ""
    }

    get exchangeCount() {
        return this._exchangeCount
    }

    set netCount(value) {
        this._netCount = value
        this.filterCountTxt.text = this._netCount + ""
    }

    get netCount() {
        return this._netCount
    }

    updateProp(bombCount: number, exchangeCount: number, netCount: number) {
        if (bombCount == 0 || bombCount !== this.bombCount) {
            this.bombCount = bombCount
        }

        if (exchangeCount == 0 || exchangeCount !== this.exchangeCount) {
            this.exchangeCount = exchangeCount
        }

        if (netCount == 0 || netCount !== this.netCount) {
            this.netCount = netCount
        }
    }

    exchangeTarget1
    exchangeTarget2
    onClick_exchangeBtn() {
        if (this.exchanging) {
            return
        }
        if (this.exchangeCount <= 0) {
            showPanel(PropOutPanel)
            return
        }
        this.exchangeBtn.mouseEnable = false
        this.showExchangeMask()
        this.onExchanging()
    }

    exchangeMask: Shape
    showExchangeMask() {
        this.exchangeMask = new Shape();
        this.exchangeMask.mouseChildren = true
        this.exchangeMask.mouseEnable = true
        this.exchangeMask.beginFill(0x000000, 0.6);
        this.exchangeMask.moveTo(0, 0)
        this.exchangeMask.lineTo(750, 0)
        this.exchangeMask.lineTo(750, 586)
        this.exchangeMask.lineTo(94, 586)
        this.exchangeMask.lineTo(94, 1140)
        this.exchangeMask.lineTo(656, 1140)
        this.exchangeMask.lineTo(656, 586)
        this.exchangeMask.lineTo(750, 586)
        this.exchangeMask.lineTo(750, 1624)
        this.exchangeMask.lineTo(0, 1624)
        this.exchangeMask.lineTo(0, 0)
        this.exchangeMask.drawCircle(180, 1340, 95, true)
        this.exchangeMask.endFill();

        this.addChild(this.exchangeMask)

        let tips = new Sprite(RES.getRes("exchangeTips.png"))
        tips.x = 140
        tips.y = 1140
        this.exchangeMask.addChild(tips)
        let func
        this.exchangeMask.addEventListener(MouseEvent.CLICK, func = () => {
            this.exchangeBtn.mouseEnable = true
            this.removeChild(this.exchangeMask)
            this.removeAllClick()
            this.removeAnis()
            for (let i = 0; i < this.exchangeTargetPool.length; i++) {
                if (this.exchangeTargetPool[i].children.length > 1) {
                    this.exchangeTargetPool[i].removeChild(this.exchangeTargetPool[i].children[1])
                }
            }

            this.exchanging = false
            this.exchangeMask.removeEventListener(MouseEvent.CLICK, func, this)
        }, this)
    }

    exchangeTargetPool
    onExchanging() {
        this.exchanging = true
        this.exchangeTargetPool = []
        let t = 1
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] > 0) {
                    this.containerPool[x][y].addEventListener(MouseEvent.CLICK, (e) => {
                        if (this.exchangeTargetPool.length > 0) {
                            let element = this.exchangeTargetPool[0]
                            if (this.containerPool[x][y] == element) {
                                // 选中同一个
                                this.containerPool[x][y].removeChild(this.containerPool[x][y].exchangeTips)
                                this.exchangeTargetPool.shift()
                                this.removeAnis()
                                return
                            }
                        }
                        this.exchangeTargetPool.push(this.containerPool[x][y])
                        this.containerPool[x][y].addChild(this['exchangeTarget' + t])
                        this.containerPool[x][y].exchangeTips = this['exchangeTarget' + t]
                        t++
                        if (t > 2) {
                            t = 1
                        }
                        this.checkExchange()
                    }, this)
                }
            }
        }
    }

    async checkExchange() {
        if (this.exchangeTargetPool.length >= 2) {
            showWaiting()
            useTools(async (s) => {
                hideWaiting()
                if (!s) {
                    //扣道具失败
                    this.removeAnis()
                    this.renderBoard()
                    this.removeChild(this.exchangeMask)
                    this.removeAllClick()
                    this.exchangeTargetPool = []
                    this.exchanging = false
                    this.exchangeBtn.mouseEnable = true
                    return
                }

                let num0 = this.board[this.exchangeTargetPool[0].cx][this.exchangeTargetPool[0].cy]
                let num1 = this.board[this.exchangeTargetPool[1].cx][this.exchangeTargetPool[1].cy]

                this.removeAnis()
                // 交换动效
                checkMusic("exchange", this.isPlayMusic)
                // 交换动效
                await this.exchangeAni()

                let tem = num0
                num0 = num1
                num1 = tem

                this.board[this.exchangeTargetPool[0].cx][this.exchangeTargetPool[0].cy] = num0
                this.board[this.exchangeTargetPool[1].cx][this.exchangeTargetPool[1].cy] = num1

                this.renderBoard()
                this.removeChild(this.exchangeMask)
                this.removeAllClick()
                this.exchangeTargetPool = []
                this.exchanging = false
                this.exchangeBtn.mouseEnable = true

                getTools()

                // if (!this.isGameWin())
                this.isGameOver()
            }, PropType.exchange)
        } else if (this.exchangeTargetPool.length = 1) {
            for (let x = 0; x < 4; x++) {
                for (let y = 0; y < 4; y++) {
                    if (this.board[x][y] > 0 && !(this.exchangeTargetPool[0].cx === x && this.exchangeTargetPool[0].cy === y)) {
                        this.containerPool[x][y].children[0].anchor.set(60, 60)
                        Tween.get(this.containerPool[x][y].children[0], { loop: true })
                            .to({ rotation: 15 }, 50)
                            .to({ rotation: -15 }, 100)
                            .to({ rotation: 0 }, 50)
                    }
                }
            }
        }
    }

    exchangeAni() {

        this.mouseEnable = false
        this.mouseChildren = false
        return new Promise((r, j) => {
            this.exchangeTargetPool[0].children[0].visible = false
            this.exchangeTargetPool[1].children[0].visible = false
            let num0 = this.board[this.exchangeTargetPool[0].cx][this.exchangeTargetPool[0].cy]
            let num1 = this.board[this.exchangeTargetPool[1].cx][this.exchangeTargetPool[1].cy]
            let sprite0 = new GameEle(num0)
            sprite0.x += this.exchangeTargetPool[0].x
            sprite0.y += this.exchangeTargetPool[0].y
            this.addChild(sprite0)
            let sprite1 = new GameEle(num1)
            sprite1.x += this.exchangeTargetPool[1].x
            sprite1.y += this.exchangeTargetPool[1].y
            this.addChild(sprite1)
            Tween.get(sprite0)
                .to({ x: sprite1.x, y: sprite1.y }, 500)

            Tween.get(sprite1)
                .to({ x: sprite0.x, y: sprite0.y }, 500)
                .call(() => {
                    this.removeChild(sprite0)
                    this.removeChild(sprite1)

                    this.mouseEnable = true
                    this.mouseChildren = true
                    r()
                })
        })
    }

    bombMask: Shape
    showBombMask() {
        this.bombMask = new Shape();
        this.bombMask.mouseChildren = true
        this.bombMask.mouseEnable = true
        this.bombMask.beginFill(0x000000, 0.6);
        this.bombMask.moveTo(0, 0)
        this.bombMask.lineTo(750, 0)
        this.bombMask.lineTo(750, 586)
        this.bombMask.lineTo(94, 586)
        this.bombMask.lineTo(94, 1140)
        this.bombMask.lineTo(656, 1140)
        this.bombMask.lineTo(656, 586)
        this.bombMask.lineTo(750, 586)
        this.bombMask.lineTo(750, 1624)
        this.bombMask.lineTo(0, 1624)
        this.bombMask.lineTo(0, 0)
        this.bombMask.drawCircle(375, 1340, 95, true)
        this.bombMask.endFill();

        this.addChild(this.bombMask)

        let tips = new Sprite(RES.getRes("bombTips.png"))
        tips.x = 280
        tips.y = 1140
        this.bombMask.addChild(tips)
        let func
        this.bombMask.addEventListener(MouseEvent.CLICK, func = () => {
            this.bombBtn.mouseEnable = true
            this.removeChild(this.bombMask)
            this.removeAllClick()
            this.bombing = false
            this.bombMask.removeEventListener(MouseEvent.CLICK, func, this)
        }, this)

    }

    onClick_bombBtn() {
        if (this.bombing) {
            return
        }
        if (this.bombCount <= 0) {
            showPanel(PropOutPanel)
            return
        }
        this.bombing = true
        this.bombBtn.mouseEnable = false
        this.showBombMask()
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] > 0) {
                    this.containerPool[x][y].addEventListener(MouseEvent.CLICK, (e) => {
                        showWaiting()
                        useTools((s) => {
                            hideWaiting()
                            if (!s) {
                                // 使用失败
                                this.removeAllClick()
                                this.removeChild(this.bombMask)
                                this.bombBtn.mouseEnable = true
                                this.bombing = false
                                return
                            }
                            getTools()
                            // 炸弹动效
                            var arr = [];
                            for (var i = 1; i <= 20; i++)arr.push(RES.getRes("bomb(" + i + ").png"));
                            let showImage = new FrameAni(arr);
                            showImage.x = this.containerPool[x][y].x + 60
                            showImage.y = this.containerPool[x][y].y + 60
                            showImage.scale.set(0.5, 0.5)
                            this.addChild(showImage);
                            showImage.play()

                            checkMusic("bomb", this.isPlayMusic)
                            setTimeout(() => {
                                this.board[x][y] = 0
                                this.renderBoard()
                                this.removeAllClick()
                                this.removeChild(this.bombMask)
                                this.bombBtn.mouseEnable = true
                                this.bombing = false
                                this.removeChild(showImage)
                            }, 300);

                        }, PropType.boom)
                    }, this)
                }
            }
        }
    }

    filterMask: Shape
    doFilterBtn
    showFilterMask() {
        this.filterMask = new Shape();
        this.filterMask.mouseChildren = true
        this.filterMask.mouseEnable = true
        this.filterMask.beginFill(0x000000, 0.6);
        this.filterMask.moveTo(0, 0)
        this.filterMask.lineTo(750, 0)
        this.filterMask.lineTo(750, 586)
        this.filterMask.lineTo(94, 586)
        this.filterMask.lineTo(94, 1140)
        this.filterMask.lineTo(656, 1140)
        this.filterMask.lineTo(656, 586)
        this.filterMask.lineTo(750, 586)
        this.filterMask.lineTo(750, 1624)
        this.filterMask.lineTo(0, 1624)
        this.filterMask.lineTo(0, 0)
        this.filterMask.drawCircle(575, 1340, 95, true)
        this.filterMask.endFill();

        this.addChild(this.filterMask)

        let tips = new Sprite(RES.getRes("filterTips.png"))
        tips.x = 360
        tips.y = 1140
        this.filterMask.addChild(tips)
        let func
        this.filterMask.addEventListener(MouseEvent.CLICK, func = () => {
            this.filterBtn.mouseEnable = true
            this.removeChild(this.filterMask)
            this.removeChild(this.doFilterBtn)
            this.removeAnis()
            this.filtering = false
            this.filterMask.removeAllEventListener()
            this.doFilterBtn.removeAllEventListener()
        }, this)

        this.doFilterBtn = new Button(RES.getRes("doFilterBtn.png"))
        this.doFilterBtn.x = 500
        this.doFilterBtn.y = 1200
        this.addChild(this.doFilterBtn)
        let btnFunc
        this.doFilterBtn.addEventListener(MouseEvent.CLICK, btnFunc = () => {
            showWaiting()
            useTools((s) => {
                hideWaiting()
                if (!s) {
                    this.filterBtn.mouseEnable = true
                    this.removeChild(this.filterMask)
                    this.removeChild(this.doFilterBtn)
                    this.filtering = false
                    this.removeAnis()
                    return
                }
                getTools()
                var arr = [];
                for (var i = 1; i <= 17; i++)arr.push(RES.getRes("filting (" + i + ").png"));
                for (let x = 0; x < 4; x++) {
                    for (let y = 0; y < 4; y++) {
                        if (this.board[x][y] > 0 && this.board[x][y] < 128) {
                            // 滤网动效
                            let showImage = new FrameAni(arr);
                            showImage.x = this.containerPool[x][y].x + 60
                            showImage.y = this.containerPool[x][y].y + 60
                            showImage.scale.set(0.9, 0.9)
                            this.addChild(showImage);
                            showImage.play()
                            setTimeout(() => {
                                this.removeChild(showImage)
                            }, 500);
                            Tween.get(this.containerPool[x][y].children[0])
                                .to({ scaleX: 0, scaleY: 0 }, 200)
                                .call(() => {
                                    this.containerPool[x][y].removeChild(this.containerPool[x][y].children[0])
                                })
                            this.board[x][y] = 0
                        }
                    }
                }
                checkMusic("bomb", this.isPlayMusic)
                this.filterMask.removeAllEventListener()
                this.doFilterBtn.removeAllEventListener()
                setTimeout(() => {
                    this.renderBoard()
                    this.filterBtn.mouseEnable = true
                    this.removeChild(this.filterMask)
                    this.removeChild(this.doFilterBtn)
                    this.filtering = false
                    this.removeAnis()
                    // if (!this.isGameWin())
                    this.isGameOver()
                }, 300);
            }, PropType.net)
        }, this)
    }

    onClick_filterBtn() {
        if (this.filtering) {
            return
        }
        if (this.netCount <= 0) {
            showPanel(PropOutPanel)
            return
        }
        this.filterBtn.mouseEnable = false
        this.filtering = true
        this.showFilterMask()
        this.filterShakeAni()

    }

    filterShakeAni() {
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] > 0 && this.board[x][y] < 128) {
                    Tween.get(this.containerPool[x][y].children[0], { loop: true })
                        .to({ rotation: 15 }, 50)
                        .to({ rotation: -15 }, 100)
                        .to({ rotation: 0 }, 50)
                }
            }
        }
    }

    removeAllClick() {
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] > 0) {
                    this.containerPool[x][y].removeAllEventListener()
                }
            }
        }
    }

    removeAnis() {
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] > 0) {
                    this.containerPool[x][y].children[0].rotation = 0
                }
            }
        }
        Tween.removeAllTweens()
    }

    startX
    startY
    offsetX = 0
    offsetY = 0

    exchanging: boolean
    bombing: boolean
    filtering: boolean
    moving: boolean
    onDown_this(e) {
        if (this.exchanging || this.bombing || this.filtering || this.moving) {
            // 交换中、使用炸弹中、过滤中、移动中  不允许滑动
            return
        }

        this.addEventListener(MouseEvent.MOUSE_MOVE, this.onMove_this, this)
        this.addEventListener(MouseEvent.MOUSE_UP, this.onUp_this, this)
        this.addEventListener(MouseEvent.MOUSE_OUT, this.onUp_this, this)
        this.startX = e.stageX
        this.startY = e.stageY
    }

    onMove_this(e) {
        this.offsetX = e.stageX - this.startX
        this.offsetY = e.stageY - this.startY

    }

    onUp_this() {

        this.removeEventListener(MouseEvent.MOUSE_MOVE, this.onMove_this, this)
        this.removeEventListener(MouseEvent.MOUSE_UP, this.onUp_this, this)
        this.removeEventListener(MouseEvent.MOUSE_OUT, this.onUp_this, this)
        this.checkMove()
        this.offsetX = 0
        this.offsetY = 0
    }

    removeEvents() {
        super.removeEvents()

        this.removeEventListener(MouseEvent.MOUSE_DOWN, this.onDown_this, this)
        GDispatcher.removeEvent("updateProp", this.updateProp, this)
        this.exchangeBtn.removeEventListener(MouseEvent.CLICK, this.onClick_exchangeBtn, this)
        this.bombBtn.removeEventListener(MouseEvent.CLICK, this.onClick_bombBtn, this)
        this.filterBtn.removeEventListener(MouseEvent.CLICK, this.onClick_filterBtn, this)
        this.musicBtn.removeEventListener(MouseEvent.CLICK, this.onClick_musicBtn, this)
        this.goBackBtn.removeEventListener(MouseEvent.CLICK, this.onClick_goBackBtn, this)
    }

    async checkMove() {
        if (this.guideMask) {
            this.removeChild(this.guideMask)
            this.guideMask = null
        }
        if (this.moving || this.exchanging || this.bombing || this.filtering) {
            return
        }
        if (this.checkAllZero()) {
            // 只有0 
            this.generateOneElement()
        }

        this.moving = true
        let beforeArr = this.cloneArr(this.board)
        if (Math.abs(this.offsetX) > Math.abs(this.offsetY)) {
            // 横向移动

            if (this.offsetX > 0) {
                console.log("右滑");
                // 复制一份原先的数组
                if (this.moveToRight(true)) {
                    checkMusic("move", this.isPlayMusic)
                    await this.moveAni(beforeArr)
                    this.renderBoard()
                    this.generateOneElement()
                    // if (!this.isGameWin())
                    this.isGameOver()
                }
            }
            if (this.offsetX < 0) {
                console.log("左滑")
                if (this.moveToLeft(true)) {
                    checkMusic("move", this.isPlayMusic)
                    await this.moveAni(beforeArr)
                    this.renderBoard()
                    this.generateOneElement()
                    // if (!this.isGameWin())
                    this.isGameOver()
                }
            }
        } else {
            // 竖向移动
            if (this.offsetY > 0) {
                console.log("下滑")
                if (this.moveToBottom(true)) {
                    checkMusic("move", this.isPlayMusic)
                    await this.moveAni(beforeArr)
                    this.renderBoard()
                    this.generateOneElement()
                    // if (!this.isGameWin())
                    this.isGameOver()
                }
            }
            if (this.offsetY < 0) {
                console.log("上滑")
                if (this.moveToTop(true)) {
                    checkMusic("move", this.isPlayMusic)
                    await this.moveAni(beforeArr)
                    this.renderBoard()
                    this.generateOneElement()
                    // if (!this.isGameWin())
                    this.isGameOver()
                }
            }
        }
        setTimeout(() => {

            this.moving = false
        }, 320);
    }

    // 克隆二位数组返回新数组
    cloneArr(arr) {
        let b = []
        for (let i = 0; i < arr.length; i++) {

            b[i] = arr[i].concat()
        }
        return b
    }

    checkAllZero() {
        let bool = true
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] !== 0) {
                    bool = false
                }
            }
        }
        return bool
    }

    drawRect(x, y, w, h, color) {
        let sprite = new Graphics();
        let _color = color ? color : 0xffffff
        sprite.x = x;
        sprite.y = y;
        // sprite.tint=0x0000ff
        // sprite.alpha=0.5
        sprite.beginFill(_color, 1);
        sprite.drawRect(x, y, x + w, y + h);
        sprite.endFill();

        return sprite
    }

    drawTxt(text, x?, y?, color?, size?) {
        if (!(text + "")) {
            return
        }
        let _text = text + ""
        let txt = new TextField();
        txt.size = 50;
        txt.fillColor = color ? color : "#ffffff";
        txt.text = _text
        txt.size = size ? size : 30
        txt.x = x ? x : 0
        txt.y = y ? y : 0
        return txt

    }

    // 随机生成基础元素
    generateOneElement() {
        // 随机生成一个数字 2or4
        let randNumber = Math.random() < 0.5 ? 2 : 2048
        // 随机生成位置
        let randNumberX = Math.floor(Math.random() * 4)
        let randNumberY = Math.floor(Math.random() * 4)
        // 检查该位置上是否已有值
        if (this.board[randNumberX][randNumberY] !== 0) {
            this.generateOneElement()
        } else {
            this.board[randNumberX][randNumberY] = randNumber

            let sprite = new GameEle(randNumber)
            this.addChild(sprite)
            sprite.x += this.containerPool[randNumberX][randNumberY].x
            sprite.y += this.containerPool[randNumberX][randNumberY].y
            sprite.scale.set(0, 0)
            sprite.anchor.set(60, 60)
            Tween.get(sprite)
                .to({ scaleX: 1, scaleY: 1 }, 300)
                .call(() => {
                    this.removeChild(sprite)

                    this.renderBoard()
                })
        }
    }

    // 渲染视图
    renderBoard() {
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                let num = this.board[x][y]
                // 添加元素
                this.containerPool[x][y].removeChildren()
                let ele = new GameEle(num)
                this.containerPool[x][y].addChild(ele)


                if (num > this.unlockGrade) {
                    // 显示解锁弹窗
                    showPanel(UnlockPanel, { grade: num })
                    this.unlockGrade = num
                }
            }
        }
    }

    // 判断此时四个方向上能否有一个能移动
    noMove() {
        if (this.moveToLeft(false) || this.moveToTop(false) || this.moveToRight(false) || this.moveToBottom(false))
            return false
        return true
    }
    // 判断此时16宫格中是否还有空格子
    noSpace() {
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] === 0) return false
            }
        }
        return true
    }

    isGameOver() {
        if (this.noSpace() && this.noMove()) {
            this.gameover()
        }
    }

    gameover() {
        // 游戏结束
        console.log("游戏结束");
        showPanel(PropPanel, {
            bombCount: this.bombCount,
            exchangeCount: this.exchangeCount,
            netCount: this.netCount,
            grade: this.unlockGrade,
            score: this.score,
        })
    }

    isGameWin() {
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.board[x][y] === 2048) {
                    this.gamewin()
                    return true
                }
            }
        }
        return false
    }

    gamewin() {
        // 游戏胜利
        console.log("游戏胜利")
    }

    currMoveType
    combineCount: number = 0
    moveToLeft(type) {
        let arr = [], tag = false
        this.currMoveType = "left"
        this.combineCount = 0
        for (let x = 0; x < 4; x++) {
            arr[x] = new Array()
            arr[x] = this.board[x]
            tag = tag || this.canMove(arr[x])
            if (type) {
                this.updateArr(arr[x], x)
            }
        }

        if (this.combineCount > 0) {
            if (this.combineCount == 1) {
                checkMusic("createEle", this.isPlayMusic)
            } else {
                checkMusic("createEles", this.isPlayMusic)
            }
        }
        if (tag && type) {
            this.board = arr
        }
        arr = null
        return tag
    }

    moveToTop(type) {
        let arr = [], tag = false
        this.currMoveType = "top"
        this.combineCount = 0
        for (let y = 0; y < 4; y++) {
            arr[y] = new Array()
            for (let x = 0; x < 4; x++) {
                arr[y].push(this.board[x][y])
            }
            tag = tag || this.canMove(arr[y])
            if (type) {
                this.updateArr(arr[y], y)

            }
        }

        if (this.combineCount > 0) {
            if (this.combineCount == 1) {
                checkMusic("createEle", this.isPlayMusic)
            } else {
                checkMusic("createEles", this.isPlayMusic)
            }
        }

        if (tag && type) {
            for (let x = 0; x < 4; x++) {
                for (let y = 0; y < 4; y++) {
                    this.board[y][x] = arr[x][y]
                }
            }
        }
        arr = null
        return tag
    }

    canMoveRight

    moveToRight(type) {
        let arr = [], tag = false
        this.currMoveType = "right"
        this.combineCount = 0
        for (let x = 0; x < 4; x++) {
            arr[x] = new Array()
            // 数组反向传入处理函数
            arr[x] = this.board[x].concat()
            // 颠倒数组
            arr[x].reverse()
            tag = tag || this.canMove(arr[x])

            if (type) this.updateArr(arr[x], x)
        }

        if (this.combineCount > 0) {
            if (this.combineCount == 1) {
                checkMusic("createEle", this.isPlayMusic)
            } else {
                checkMusic("createEles", this.isPlayMusic)
            }
        }

        // 数组再一次反向 即为此方向上的正确值顺序
        if (tag && type) {
            for (let x = 0; x < 4; x++) {
                this.board[x] = arr[x].reverse()
            }
        }
        arr = null
        // this.canMoveRight = tag
        return tag
    }

    canMoveBottom
    moveToBottom(type) {
        let arr = [], tag = false
        this.currMoveType = "bottom"
        this.combineCount = 0
        for (let y = 0; y < 4; y++) {
            arr[y] = new Array()
            for (let x = 0; x < 4; x++) {
                arr[y].unshift(this.board[x][y])
            }
            tag = tag || this.canMove(arr[y])
            if (type) this.updateArr(arr[y], y)
        }

        if (this.combineCount > 0) {

            if (this.combineCount == 1) {
                checkMusic("createEle", this.isPlayMusic)
            } else {
                checkMusic("createEles", this.isPlayMusic)
            }
        }

        if (tag && type) {
            for (let x = 0; x < 4; x++) {
                arr[x].reverse()
                for (let y = 0; y < 4; y++) {
                    this.board[y][x] = arr[x][y]
                }
            }
        }
        arr = null
        this.canMoveBottom = tag
        return tag
    }

    moveData = [[], [], [], []]
    scoreTips: TextField
    updateArr(arr, t = 0) {
        this.moveData = [[], [], [], []]
        // 先删除数组中的0
        let tag = 0

        for (let i = 0; i < arr.length; i++) {  // 4次

            if (arr[tag] === 0) {
                arr.splice(tag, 1)
                arr.push(0)
            } else {
                tag++
                continue
            }
        }
        // 判断相加/合并
        let addScore = 0
        for (let i = 1; i < arr.length; i++) {
            if (arr[i] === 0) break
            if (arr[i] === arr[i - 1] && arr[i - 1] < 2048) {

                // fromIdx 要改成转换前的idx
                // this.moveData[t].push({ "fromValue": arr[i - 1], "toValue": arr[i - 1] * 2, "fromIdx": i, "toIdx": i - 1 })
                let ti = 0
                let target = { "row": 0, "col": 0 }
                switch (this.currMoveType) {
                    case "left":
                        ti = i - 1
                        target = { "row": t, "col": ti }
                        break;
                    case "top":
                        ti = i - 1
                        target = { "row": ti, "col": t }
                        break;
                    case "right":
                        ti = 3 - (i - 1)
                        target = { "row": t, "col": ti }
                        break;
                    case "bottom":
                        ti = 3 - (i - 1)
                        target = { "row": ti, "col": t }
                        break
                }
                let clone = this.containerPool[target.row][target.col]
                // console.log(clone)
                // this.addChild(clone)
                Tween.get(clone)
                    .set({ scaleX: 1, scaleY: 1, anchorX: 75, anchorY: 75 })
                    .to({ scaleX: 0.3, scaleY: 0.3 }, 100)
                    .to({ scaleX: 1.3, scaleY: 1.3 }, 300)
                    .to({ scaleX: 1, scaleY: 1 }, 150)

                arr[i - 1] *= 2
                arr.splice(i, 1)
                arr.push(0)

                this.combineCount++

                //一次性走完就让 i = 0 例如 2240 =》8000
                //i = 0    //此处不能 i -= 1 [8,2,2,4]会出问题

                // 播放对应合成svga
                this.createArr.forEach((num, idx) => {
                    if (num === arr[i - 1]) {
                        let mp = new MovieClip(this.createAniPool[idx])
                        mp.x = this.containerPool[target.row][target.col].x - 70
                        mp.y = this.containerPool[target.row][target.col].y - 70
                        this.addChild(mp)
                        mp.startAniRange(0)

                        setTimeout(() => {
                            this.removeChild(mp)
                        }, 1000);
                    }
                })

                addScore += arr[i - 1]
                this.score += arr[i - 1]
            }

            if (addScore > 0) {
                this.scoreTips = this.drawTxt("+" + addScore, 250, 340, "#ffffff", 34)
                this.scoreTips.alpha = 0
                this.addChild(this.scoreTips)
                Tween.get(this.scoreTips)
                    .to({ y: 300, alpha: 1 }, 200)
                    .wait(200)
                    .to({ y: 250, alpha: 0 }, 100)
                    .call(() => {
                        this.removeChild(this.scoreTips)
                    })
            }

        }
    }

    moveAni(beforeArr) {
        return new Promise((r, j) => {
            switch (this.currMoveType) {
                case "top":
                    for (let y = 0; y < 4; y++) {
                        for (let x = 0; x < 4; x++) {
                            for (let xb = x + 1; xb < 4; xb++) {
                                if (beforeArr[xb][y] > 0) {
                                    if (beforeArr[x][y] === 0) {
                                        this.containerPool[xb][y].children[0].visible = false
                                        let origin = new GameEle(beforeArr[xb][y])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[xb][y].x
                                        origin.y += this.containerPool[xb][y].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[x][y] = beforeArr[xb][y]
                                        beforeArr[xb][y] = 0
                                    } else if (beforeArr[xb][y] === beforeArr[x][y] && noBlockBottom(x, xb, y, beforeArr) && beforeArr[x][y] < 2048) {
                                        this.containerPool[xb][y].children[0].visible = false
                                        let origin = new GameEle(beforeArr[xb][y])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[xb][y].x
                                        origin.y += this.containerPool[xb][y].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[xb][y] = 0
                                        beforeArr[x][y] *= 2
                                    }
                                }
                            }
                        }
                    }
                    break;
                case "left":
                    for (let x = 0; x < 4; x++) {
                        for (let y = 0; y < 4; y++) {
                            for (let yr = y + 1; yr < 4; yr++) {
                                if (beforeArr[x][yr] > 0) {
                                    if (beforeArr[x][y] === 0) {
                                        this.containerPool[x][yr].children[0].visible = false
                                        let origin = new GameEle(beforeArr[x][yr])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[x][yr].x
                                        origin.y += this.containerPool[x][yr].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[x][y] = beforeArr[x][yr]
                                        beforeArr[x][yr] = 0
                                    } else if (beforeArr[x][yr] === beforeArr[x][y] && noBlockRight(x, y, yr, beforeArr) && beforeArr[x][y] < 2048) {
                                        this.containerPool[x][yr].children[0].visible = false
                                        let origin = new GameEle(beforeArr[x][yr])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[x][yr].x
                                        origin.y += this.containerPool[x][yr].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[x][y] *= 2
                                        beforeArr[x][yr] = 0
                                    }
                                }
                            }
                        }
                    }
                    break
                case "bottom":
                    for (let y = 0; y < 4; y++) {
                        for (let x = 3; x >= 0; x--) {
                            for (let xt = x - 1; xt >= 0; xt--) {
                                if (beforeArr[xt][y] > 0) {
                                    if (beforeArr[x][y] === 0) {
                                        this.containerPool[xt][y].children[0].visible = false
                                        let origin = new GameEle(beforeArr[xt][y])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[xt][y].x
                                        origin.y += this.containerPool[xt][y].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[x][y] = beforeArr[xt][y]
                                        beforeArr[xt][y] = 0
                                    } else if (beforeArr[xt][y] === beforeArr[x][y] && noBlockTop(x, xt, y, beforeArr) && beforeArr[x][y] < 2048) {
                                        this.containerPool[xt][y].children[0].visible = false
                                        let origin = new GameEle(beforeArr[xt][y])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[xt][y].x
                                        origin.y += this.containerPool[xt][y].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[xt][y] = 0
                                        beforeArr[x][y] *= 2
                                    }
                                }
                            }
                        }
                    }
                    break
                case "right":
                    for (let x = 0; x < 4; x++) {
                        for (let y = 3; y >= 0; y--) {
                            for (let yl = y - 1; yl >= 0; yl--) {
                                if (beforeArr[x][yl] > 0) {
                                    if (beforeArr[x][y] === 0) {
                                        this.containerPool[x][yl].children[0].visible = false
                                        let origin = new GameEle(beforeArr[x][yl])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[x][yl].x
                                        origin.y += this.containerPool[x][yl].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[x][y] = beforeArr[x][yl]
                                        beforeArr[x][yl] = 0
                                    } else if (beforeArr[x][yl] === beforeArr[x][y] && noBlockLeft(x, y, yl, beforeArr) && beforeArr[x][y] < 2048) {
                                        this.containerPool[x][yl].children[0].visible = false
                                        let origin = new GameEle(beforeArr[x][yl])
                                        this.addChild(origin)
                                        let ox = origin.x
                                        let oy = origin.y
                                        origin.x += this.containerPool[x][yl].x
                                        origin.y += this.containerPool[x][yl].y
                                        let targetx = this.containerPool[x][y].x + ox
                                        let targety = this.containerPool[x][y].y + oy
                                        Tween.get(origin)
                                            .to({ x: targetx, y: targety }, 200)
                                            .call(() => {
                                                this.removeChild(origin)
                                            })

                                        beforeArr[x][yl] = 0
                                        beforeArr[x][y] *= 2
                                    }
                                }
                            }
                        }
                    }
                    break
            }
            setTimeout(() => {
                r()
            }, 200);

        })
    }


    canMove(arr: any[]) {
        let hasZero = false
        for (let i = 0; i < arr.length; i++) {
            if (arr[i] === 0) {
                hasZero = true
            } else if (arr[i] !== 0 && hasZero || (arr[i] === arr[i + 1] && arr[i] < 2048)) {
                return true
            } else {
                continue
            }
        }
        return false
    }

}