import { DisplayObject } from './../../../engine/2d/display/DisplayObject';
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';
export class PlayScene extends Scene {
    get groupNames() { return ["playScene"] }

    constructor() {
        super()
    }

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

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

    _score = 0

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

    get score() {
        return this._score
    }

    _unlockScore = 2
    set unlockScore(value) {
        this._unlockScore = value
        this.unlockScoreTxt.text = this._unlockScore + ""
    }
    get unlockScore() {
        return this._unlockScore
    }

    bg: Sprite
    bombBtn: Button
    exchangeBtn: Button
    filterBtn: Button
    scoreTxt: TextField
    unlockScoreTxt: 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.unlockScoreTxt = this.addChild(this.drawTxt(this.unlockScore, 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)

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

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

        for (let x = 0; x < 4; x++) {
            this.board[x] = []
            this.containerPool[x] = []
            let py = 615 + x * 139
            for (let y = 0; y < 4; y++) {
                let num = 0
                this.board[x][y] = num
                let px = 110 + y * 138
                let container = new Container();
                container.x = px
                container.y = py
                container["idx"] = x + y + ""
                this.addChild(container);
                container.addChild(new GameEle(num))
                this.containerPool[x][y] = container
            }
        }

        this.generateOneElement()
        this.generateOneElement()
    }

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

    initEvents() {
        super.initEvents()
        this.addEventListener(MouseEvent.MOUSE_DOWN, this.onDown_this, this)
        this.addEventListener(MouseEvent.CLICK, this.onClick_exchangeBtn, this)
        this.addEventListener(MouseEvent.CLICK, this.onClick_bombBtn, this)
        this.addEventListener(MouseEvent.CLICK, this.onClick_filterBtn, this)
    }

    onClick_exchangeBtn() {

    }

    onClick_bombBtn() {

    }

    onClick_filterBtn() {

    }

    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)
        this.removeEventListener(MouseEvent.CLICK, this.onClick_exchangeBtn, this)
        this.removeEventListener(MouseEvent.CLICK, this.onClick_bombBtn, this)
        this.removeEventListener(MouseEvent.CLICK, this.onClick_filterBtn, this)
    }

    async checkMove() {
        if (Math.abs(this.offsetX) > Math.abs(this.offsetY)) {
            // 横向移动
            if (this.offsetX > 0) {
                console.log("右滑");
                if (this.moveToRight(true)) {
                    this.renderBoard()
                    this.generateOneElement()
                    if (!this.isGameWin())
                        this.isGameOver()
                }
            }
            if (this.offsetX < 0) {
                console.log("左滑")
                if (this.moveToLeft(true)) {
                    // await this.moveAni()
                    this.renderBoard()
                    this.generateOneElement()
                    if (!this.isGameWin())
                        this.isGameOver()
                }
            }
        } else {
            // 竖向移动
            if (this.offsetY > 0) {
                console.log("下滑")
                if (this.moveToBottom(true)) {
                    this.renderBoard()
                    this.generateOneElement()
                    if (!this.isGameWin())
                        this.isGameOver()
                }
            }
            if (this.offsetY < 0) {
                console.log("上滑")
                if (this.moveToTop(true)) {
                    this.renderBoard()
                    this.generateOneElement()
                    if (!this.isGameWin())
                        this.isGameOver()
                }
            }
        }
    }



    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 : 4
        // 随机生成位置
        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
        }
        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()
                this.containerPool[x][y].addChild(new GameEle(num))
                if (num >= this.unlockScore) {
                    this.unlockScore = 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("游戏结束");

    }

    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
    moveToLeft(type) {
        let arr = [], tag = false
        this.currMoveType = "left"
        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 (tag && type) {
            this.board = arr
        }
        arr = null
        return tag
    }

    moveToTop(type) {
        let arr = [], tag = false
        this.currMoveType = "top"
        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 (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"
        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 (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"
        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 (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 = [[], [], [], []]
    updateArr(arr, t = 0) {
        this.moveData = [[], [], [], []]
        // 先删除数组中的0
        let tag = 0
        for (let i = 0; i < arr.length; i++) {
            if (arr[tag] === 0) {
                arr.splice(tag, 1)
                arr.push(0)
            } else {
                tag++
                continue
            }
        }
        // 判断相加/合并
        for (let i = 1; i < arr.length; i++) {
            if (arr[i] === 0) break
            if (arr[i] === arr[i - 1]) {

                // 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: 1.5, scaleY: 1.5 }, 300)
                    .to({ scaleX: 1, scaleY: 1 }, 300)
                    .to({ scaleX: 1.5, scaleY: 1.5 }, 300)
                    .to({ scaleX: 1, scaleY: 1 }, 300)

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

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

    moveAni() {
        return new Promise((r, j) => {

            switch (this.currMoveType) {
                case "top":

                    break;
                case "left":
                    this.moveData.reverse()
                    this.moveData.forEach((arr, idx) => {
                        if (arr instanceof Array && arr.length > 0) {
                            console.log(arr[0], idx);

                        }
                    })
                    break
                case "bottom":
                    break
                case "right":
                    break
            }

            r()
        })
    }

    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]) {
                return true
            } else {
                continue
            }
        }
        return false
    }

}