
import { JellySpreadAni } from "../anis/JellySpreadAni";
import { Pool } from "../Pool";
import { RecoverName } from "../enum/RecoverName";
import { Tool } from "../Tool";
import { ElementType } from "../enum/ElementType";
import { Lattice } from "../class/Lattice";
import { ChickenEgg } from "../class/ChickenEgg";
import { HatchAni } from "../anis/HatchAni";
import { PieceToEggAni } from "../anis/PieceToEggAni";
import { StateType } from "../enum/StateType";
import { BubbleAni } from "../anis/BubbleAni";
import { Element } from "../class/Element";
import { HairballBrownState } from "../states/HairballBrownState";
import { HairballJumpAni } from "../anis/HairballJumpAni";
import { HairballBrownDivideAni } from "../anis/HairballBrownDivideAni";

import { getRotByTwoVectors } from "../anis/MagicRotateAni";
import { FesRedShootAni } from "../anisCall/FesRedShootAni";
import { Door } from "../class/Door";
import { DoorChangeAni } from "../anisCall/DoorChangeAni";
import { PlayScene } from "../../scene/PlayScene";


//孵鸡的数量
const chickenNum: number = 4;


//节日大红包的小红包数量
export const fesELeSmallNum: number = 6;


//很多motion在石门关闭时都不能触发，暂时就只有石门，以后有多出来的再独立封装
export class AiControl {
    private static _ins: AiControl
    /**
     * 只实例一次，所以不能直接把thisObj干进来，每个方法里带吧
     */
    static get ins() {
        return AiControl._ins || (AiControl._ins = new AiControl())
    }
    /**
     * 判断是否还有果冻，暂时不考虑果冻无中生有，否则逻辑修改
     */
    private hasJelly: boolean;
    /**
     * 提前记录所有的鸡蛋的索引，因为鸡蛋数量不会改变
     */
    private eggs: number[];
    /**
     * 判断是否还有气泡，气泡能生成，没用了
     */
    private hasBubble: boolean;
    /**
     * 判断是否还有毛球，暂时不考虑毛球能再生，以后可能改能掉落毛球，再说
     */
    private hasHairball: boolean;

    /**
     * 判断是否还有节日大红包，不可再生，暂时且只有一个
     */
    private hasFesEleBig: boolean;

    /**
     * 提前记录所有的石门的索引，因为石门数量不会改变
     */
    private doors: number[]
    /**
     * 用于判断格子中
     * 是否有果冻，
     * 是否有鸡蛋，所有带鸡蛋的格子的索引
     * 是否有毛球，
     * 是否有变色气泡，
     * 必须在初始化元素后执行，每关进入游戏都会初始化
     * @param lattices
     */
    init(lattices: Lattice[]) {
        this.hasJelly = judgeJellyExist(lattices);
        // this.hasBubble = judgeBubbleExist(lattices);
        this.hasHairball = judgeHairballExist(lattices);
        this.eggs = getEggs(lattices);

        this.hasFesEleBig = judgeFesEleBigExist(lattices)

        this.doors = getDoors(lattices);
    }

    doorMotion(thisObj: PlayScene, callback: Function) {
        //无石门，直接回调，或者非手动触发的消除，不算一轮
        if (!this.doors.length || !thisObj.isMouseAction) {
            callback();
            return
        }
        thisObj.isMouseAction = false;
        var activeDoorIndexs: number[] = []
        //找出所有激活的石门的索引
        for (var i = 0; i < this.doors.length; i++) {
            var index = this.doors[i];
            var door: Door = thisObj.lattices[index].door;
            //修改状态
            door.statusNum--;
            //石门激活
            if (door.isActive) activeDoorIndexs.push(index);
        }
        //无激活的石门，直接回调
        if (!activeDoorIndexs.length) {
            callback();
            return
        }
        //执行动画等
        let count = 0;
        let countAll = activeDoorIndexs.length;
        for (var i = 0; i < activeDoorIndexs.length; i++) {
            let index = activeDoorIndexs[i];
            let lat = thisObj.lattices[index];
            //处理空格
            if (!lat.element) {
                //即将关闭，去掉空格
                if (!lat.door.closed) {
                    Tool.removeEle(index, thisObj.emptys)
                }
                //即将打开，加回空格
                else {
                    thisObj.emptys.push(index);
                }
            }
            //动画
            let doorChangeAni: DoorChangeAni = Pool.takeOut(RecoverName.DOORCHANGE_ANI)
            if (!doorChangeAni) {
                doorChangeAni = new DoorChangeAni(lat)
            }
            thisObj.addChild(doorChangeAni);
            //隐藏原来的
            lat.door.visible = false;
            if (lat.ice) lat.ice.visible = false;
            if (lat.element) lat.element.visible = false;
            doorChangeAni.play(lat, () => {
                lat.door.visible = true;
                //最终状态时打开的，恢复
                if (!lat.door.closed) {
                    if (lat.ice) lat.ice.visible = true;
                    if (lat.element) lat.element.visible = true;
                }
                if (++count == countAll) {
                    setTimeout(() => {
                        //先检查掉落
                        thisObj.fall(() => {
                            //掉落停止回调
                            thisObj.fallCallback();
                        });
                    }, 200)
                }
            })
            //数据修改
            lat.door.closed = !lat.door.closed;
            lat.door.isActive = false;


        }

    }

    fesEleMotion(thisObj: PlayScene, callback: Function) {
        //无节日大红包，直接回调，
        if (!this.hasFesEleBig) {
            callback();
            return
        }
        //找出所有的节日大红包
        var indexs: number[] = [];
        for (var i = 0; i < thisObj.lattices.length; i++) {
            var lat = thisObj.lattices[i];
            if (lat &&
                lat.element &&
                lat.element.type == ElementType.FESTIVALELE_BIG //&&
                // lat.element.festivalEle.isActive  //是否激活在下面判断，这里收集所有，为了标记hasFesEleBig
            ) {
                indexs.push(i);
            }
        }
        //没有节日大红包，直接回调
        if (!indexs.length) {
            //标记无节日大红包
            this.hasFesEleBig = false;
            callback();
            return
        }
        //当前就一个红包，如果被石门关闭着
        if (thisObj.lattices[indexs[0]].doorClosed) {
            callback();
            return
        }
        //当前就一个红包，如果没激活就回调
        if (!thisObj.lattices[indexs[0]].element.festivalEle.isActive) {
            callback();
            return
        }

        //找出6个能飞的小红包
        var redIndexs: number[] = [];
        for (var a = 0; a < thisObj.lattices.length; a++) {
            var lat = thisObj.lattices[a];
            //是基础元素，但是不能有任何状态,  考虑修改小红包属性为可fall，
            if (Tool.judgeBaseEle(lat) &&
                !lat.element.hasAnyState() &&
                !lat.doorClosed  //石门未关闭
            ) {
                redIndexs.push(a);
            }
        }
        //打乱索引
        redIndexs.sort(function () { return (0.5 - Math.random()); });
        let six: any[] = redIndexs.splice(0, fesELeSmallNum);
        //如果不足6个，就修改thisObj里的
        if (six.length < fesELeSmallNum) {
            thisObj.festivalTargetNum = fesELeSmallNum;
            thisObj.festivalTarget.count = fesELeSmallNum;
            //如果是0;就直接发接口吧
            if (!six.length) {//先去掉
                // NetManager.ins.hc_redBombAward((success) => {
                //     if (success) thisObj.redBombPanelMark = true;
                // });
                callback();
                return
            }
        }
        //变成对象
        for (var i = 0; i < six.length; i++) six[i] = { index: six[i] };
        //暂时只有一个大红包，
        let index = indexs[0];
        var p = Tool.getPositionByIndex(index);
        var vec0 = [1, 0];
        //计算角度
        for (var i = 0; i < six.length; i++) {
            var po = Tool.getPositionByIndex(six[i].index);
            var deltaX = po[0] - p[0];
            var deltaY = po[1] - p[1];
            // var dis = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
            //算角度，弧度，x正方向为0，0到2pi，逆时针为正
            var vec1 = [deltaX, deltaY]
            var rotation = getRotByTwoVectors(vec0, vec1);
            if (deltaY > 0) rotation = Math.PI * 2 - rotation;
            six[i].rotation = rotation;
        }
        //排序
        six.sort(function (a, b) { return b.rotation - a.rotation });
        //还原为索引
        for (var i = 0; i < six.length; i++) six[i] = six[i].index;
        //动画
        thisObj.redBombLightAni(index, (node) => {
            let count = 0;
            let countAll = six.length;
            for (let a = 0; a < six.length; a++) {
                let endIndex = six[a];
                let lat = thisObj.lattices[endIndex];
                let ele = lat.element;
                let fesRedShootAni: FesRedShootAni = Pool.takeOut(RecoverName.FESREDSHOOT_ANI)
                if (!fesRedShootAni) fesRedShootAni = new FesRedShootAni();
                setTimeout(() => {
                    thisObj.addChild(fesRedShootAni);
                    fesRedShootAni.play(p, ele, () => {
                        if (++count == countAll) {
                            //去掉大红包
                            thisObj.removeOperation(index);
                            //进行掉落
                            thisObj.fall(() => {
                                thisObj.fallCallback();
                            });
                            thisObj.removeChild(node);
                            // callback();
                        }
                    })
                }, 100 * a)
            }
        })
    }

    jellyMotion(thisObj: PlayScene, callback: Function) {
        //没有果冻，或上一步有果冻被消除，直接回调
        if (!this.hasJelly || thisObj.jellyBrokenMark) {
            callback();
            //都要标记置否
            thisObj.jellyBrokenMark = false;
            return
        }
        //标识记为false
        thisObj.jellyBrokenMark = false;
        //找出所有果冻索引
        var indexs: number[] = [];
        for (var i = 0; i < thisObj.lattices.length; i++) {
            var lattice = thisObj.lattices[i]
            //没有格子或没有元素或不是果冻 跳过
            if (!lattice || !lattice.element || lattice.element.type != ElementType.JELLY) continue
            indexs.push(i);
        }
        //如果没有果冻，直接回调
        if (!indexs.length) {
            //标记为无果冻
            this.hasJelly = false;
            callback();
            return
        }
        //去掉石门关闭的那些
        indexs = indexs.filter(function (s) { return !thisObj.lattices[s].doorClosed });
        //获取果冻动画,0是自身索引，1是终点索引
        let spread: number[];
        while (indexs.length) {
            //随机取
            var rand = Math.floor(Math.random() * indexs.length);
            var randIndex = indexs.splice(rand, 1)[0];
            var index = judgeActionIndex(randIndex, thisObj.lattices);
            //考虑0，判断null，有就break
            if (index != null) {
                //能蔓延，返回自身索引和蔓延的索引
                spread = [randIndex, index];
                break;
            }
        }
        //如果没有能蔓延的，直接回调
        if (!spread) {
            callback();
            return
        }
        //果冻蔓延动画
        let jellySpreadAni: JellySpreadAni = Pool.takeOut(RecoverName.JELLYSPREAD_ANI)
        if (!jellySpreadAni) {
            jellySpreadAni = new JellySpreadAni()
        }
        thisObj.addChild(jellySpreadAni);
        //起始元素
        let fromEle: Element = thisObj.lattices[spread[0]].element;
        //终点元素
        let endEle: Element = thisObj.lattices[spread[1]].element;
        //克隆一个终点元素
        let cloneEle: Element = endEle.clone();
        //对后续有影响的数据必须提交更新，视图不对就隐藏先，动画里加上对应视图，动画播放回调里去掉动画视图，显示数据视图；
        //将终点元素变成果冻，，
        endEle.reset(ElementType.JELLY);
        //隐藏元素
        fromEle.visible = false;
        endEle.visible = false;
        jellySpreadAni.play(
            Tool.getPositionByIndex(spread[0]),
            cloneEle,
            () => {
                //显示隐藏元素
                fromEle.visible = true;
                endEle.visible = true;
                //执行回调
                callback()
            })
    }
    /**
     * 鸡蛋得孵化逻辑
     * 与果冻不同，需要执行一次threeMatch，如无再执行callback，否则执行eleminate
     * @param thisObj
     * @param callback
     */
    eggMotion(thisObj: PlayScene, callback: Function) {
        //无蛋，直接回调
        if (!this.eggs.length) {
            callback();
            return
        }
        var activeEggIndexs: number[] = []
        //找出所有有鸡的蛋的索引
        for (var i = 0; i < this.eggs.length; i++) {
            var index = this.eggs[i];
            var egg: ChickenEgg = thisObj.lattices[index].element.chickenEgg
            //鸡蛋激活，且石门开启的
            if (egg.isActive && !thisObj.lattices[index].doorClosed) activeEggIndexs.push(index);
        }
        //无有鸡的蛋，直接回调
        if (!activeEggIndexs.length) {
            callback();
            return
        }

        //找出所有能飞小鸡的格子索引
        var chickenIndexs: number[] = [];
        for (var a = 0; a < thisObj.lattices.length; a++) {
            var lat = thisObj.lattices[a];
            //是基础元素，但是不能有任何状态，去掉鸡，且石门未关闭
            if (Tool.judgeSetChicken(lat)) chickenIndexs.push(a);
        }
        //如果没有能飞的格子,直接回调
        if (!chickenIndexs.length) {
            callback();
            return
        }
        //打乱索引
        chickenIndexs.sort(function () {
            return (0.5 - Math.random());
        });
        //拷贝
        var chickenIndexsCopy = chickenIndexs.slice();

        let countAll = activeEggIndexs.length;
        let count = 0;
        //开始给每个有鸡的蛋做匹配
        for (var b = 0; b < activeEggIndexs.length; b++) {
            let activeEggIndex = activeEggIndexs[b];
            //从chickenIndexsCopy取四个，不足就在chickenIndexs随个
            let four: number[] = chickenIndexsCopy.splice(0, chickenNum);
            if (four.length < chickenNum) {
                //补上剩下的，如果还不足，就不管
                four = four.concat(Tool.getRandomArrayElementsEx(chickenIndexs, chickenNum - four.length))
            }
            //四个元素变成鸡的数据更新在动画播放完的函数里执行，暂时对数据无影响，延后更新数据无妨
            //播蛋壳动画
            let activeEgg = thisObj.lattices[activeEggIndex].element.chickenEgg;
            activeEgg.visible = false;
            HatchAni(activeEggIndex, four, thisObj, () => {
                //飞完后恢复蛋的状态
                //蛋壳变为蛋的动画,回调里执行吧
                let pieceToEggAni: PieceToEggAni = Pool.takeOut(RecoverName.PIECETOEGG_ANI)
                if (!pieceToEggAni) {
                    pieceToEggAni = new PieceToEggAni()
                }
                thisObj.addChild(pieceToEggAni);
                pieceToEggAni.play(Tool.getPositionByIndex(activeEggIndex), () => {
                    activeEgg.reset();
                    activeEgg.visible = true;
                })

                if (++count == countAll) {
                    //做个延时，有节奏感
                    setTimeout(() => {
                        //检测三消，有就执行消除，没有就回调
                        if (thisObj.threeMatch()) {
                            thisObj.eliminate();
                        } else {
                            callback()
                        }
                    }, 200)
                }
            })
        }
    }

    /**
     * 变色气泡
     *
     * @param thisObj
     * @param callback
     */
    bubbleMotion(thisObj: PlayScene, callback: Function) {
        //无气泡，直接回调，气泡能生成，不能直接判断
        // if (!this.hasBubble) {
        //     callback();
        //     return
        // }
        //找出所有的气泡，必须按顺序，从左到右，从上到下
        var indexs: number[] = [];
        for (var i = 0; i < thisObj.lattices.length; i++) {
            var lat = thisObj.lattices[i];
            //是基础元素，有气泡状态，且石门开启
            if (Tool.judgeBaseEle(lat) &&
                lat.element.hasState(StateType.BUBBLE) &&
                !lat.doorClosed
            ) {
                indexs.push(i);
            }
        }
        //没有气泡，直接回调，
        if (!indexs.length) {
            //标记无气泡
            // this.hasBubble = false;
            callback();
            return
        }
        let count = 0;
        let countAll = indexs.length;
        //对所有气泡进行变色处理
        for (var a = 0; a < countAll; a++) {
            let index = indexs[a];
            let lat = thisObj.lattices[index];
            let ele = lat.element;
            let fromType = ele.type;
            //计算type
            let type: ElementType = getBubbleType(index, thisObj.lattices, thisObj.chapterData.baseElementTypes);
            //直接重置类型，为了后续计算泡泡类型，但是要隐藏，待动画播放完显示
            ele.resetType(type);
            ele.visible = false;
            //变色动画
            let bubbleAni: BubbleAni = Pool.takeOut(RecoverName.BUBBLE_ANI)
            if (!bubbleAni) {
                bubbleAni = new BubbleAni()
            }
            //位置信息
            var p = Tool.getPositionByIndex(index);
            bubbleAni.x = p[0];
            bubbleAni.y = p[1];
            //估计得加在元素容器那一层，不然wonderfull等toast会被动画盖掉，
            //其他也有问题的，考虑这方面，估计暂时就果冻和气泡，因为这俩动画在toast后面
            thisObj.elementContainer.addChild(bubbleAni);
            //播放动画
            bubbleAni.play(fromType, type, () => {
                //显示
                ele.visible = true;
                if (++count == countAll) callback();
            })
        }
    }

    /**
     * 跳动，以及褐色毛球的分裂
     * 黑色毛球眩晕不执行跳动，不过结束后要重置为不眩晕状态，和callback同步执行
     * @param thisObj
     * @param callback
     */
    hairballMotion(thisObj: PlayScene, callback: Function) {
        //没有毛球。直接回调
        if (!this.hasHairball) {
            callback();
            return
        }
        //找出所有能跳动的毛球;需要记录类型
        var jumpBallIndexs: { type: StateType, index: number }[] = [];
        //即将唤醒的黑色毛球
        var awakeBallIndexs: number[] = [];
        //即将分裂的褐色毛球
        var divideBallIndexs: number[] = [];
        for (var i = 0; i < thisObj.lattices.length; i++) {
            var lat = thisObj.lattices[i];
            //是基础元素，且石门非关闭
            if (Tool.judgeBaseEle(lat) && !lat.doorClosed) {
                //灰色直接进跳动
                if (lat.element.hasState(StateType.HAIRBALLGREY)) {
                    jumpBallIndexs.push({ type: StateType.HAIRBALLGREY, index: i });
                }
                //黑色
                if (lat.element.hasState(StateType.HAIRBALLBLACK)) {
                    //醒着的跳动
                    if (lat.element.getState(StateType.HAIRBALLBLACK).isAwake) {
                        jumpBallIndexs.push({ type: StateType.HAIRBALLBLACK, index: i });
                    }
                    //晕着的即将醒
                    else {
                        awakeBallIndexs.push(i);
                    }
                }
                //褐色
                if (lat.element.hasState(StateType.HAIRBALLBROWN)) {
                    //激活的即将分裂
                    if (lat.element.getState(StateType.HAIRBALLBROWN).isActive) {
                        divideBallIndexs.push(i);
                    }
                    //未激活的跳动
                    else {
                        jumpBallIndexs.push({ type: StateType.HAIRBALLBROWN, index: i });
                    }
                };
            }
        }
        //没有毛球，直接回调，
        if (!jumpBallIndexs.length && !awakeBallIndexs.length && !divideBallIndexs.length) {
            //标记无毛球
            this.hasHairball = false;
            callback();
            return
        }
        let count = 0;
        let countAll = (jumpBallIndexs.length ? 1 : 0) + (awakeBallIndexs.length ? 1 : 0) + (divideBallIndexs.length ? 1 : 0)

        //回调操作
        let callbackOperation = () => {
            if (++count == countAll) {
                setTimeout(() => {
                    //检测三消，有就执行消除，没有就回调
                    if (thisObj.threeMatch()) {
                        thisObj.eliminate();
                    } else {
                        callback()
                    }
                }, 200)
            }
        }

        //分裂的优先，因为存在多出状态，不需要多次，按顺序就行
        this.divideAni(thisObj, divideBallIndexs, callbackOperation)
        //跳动的，
        this.jumpAni(thisObj, jumpBallIndexs, callbackOperation)
        //唤醒的
        this.awakeAni(thisObj, awakeBallIndexs, callbackOperation)
    }

    private divideAni(thisObj: PlayScene, indexs: number[], callback: Function) {
        let count = 0;
        let countAll = indexs.length;
        for (var a = 0; a < countAll; a++) {
            let indexFrom = indexs[a];
            let elementFrom: Element = thisObj.lattices[indexFrom].element;
            //判断是否能分裂
            let indexEnd = judgeActionIndex(indexFrom, thisObj.lattices);
            //有执行分裂动画
            if (indexEnd != null) {
                //去掉原先的褐色
                elementFrom.setState(StateType.HAIRBALLBROWN, false);
                //变成灰色毛球
                elementFrom.setState(StateType.HAIRBALLGREY, true);
                let elementEnd = thisObj.lattices[indexEnd].element;
                //变成灰色毛球
                elementEnd.setState(StateType.HAIRBALLGREY, true);
                //两个都隐藏
                elementFrom.getState(StateType.HAIRBALLGREY).visible = false;
                elementEnd.getState(StateType.HAIRBALLGREY).visible = false;
                //分裂动画
                let divideAni: HairballBrownDivideAni = Pool.takeOut(RecoverName.HAIRBALLBROWNDIVIDE_ANI)
                if (!divideAni) divideAni = new HairballBrownDivideAni()
                thisObj.addChild(divideAni);
                divideAni.play(Tool.getPositionByIndex(indexFrom), Tool.getPositionByIndex(indexEnd), () => {
                    //显示
                    elementFrom.getState(StateType.HAIRBALLGREY).visible = true;
                    elementEnd.getState(StateType.HAIRBALLGREY).visible = true;

                    //都执行了
                    if (++count == countAll) callback();
                })
                // setTimeout(()=>{
                //     if (++count == countAll) callback();
                // },200)
            }
            //没有则执行传自身位置
            else {
                //去掉原先的褐色
                elementFrom.setState(StateType.HAIRBALLBROWN, false);
                //变成灰色毛球
                elementFrom.setState(StateType.HAIRBALLGREY, true);
                //隐藏
                elementFrom.getState(StateType.HAIRBALLGREY).visible = false;
                //动画
                let divideAni: HairballBrownDivideAni = Pool.takeOut(RecoverName.HAIRBALLBROWNDIVIDE_ANI)
                if (!divideAni) divideAni = new HairballBrownDivideAni()
                thisObj.addChild(divideAni);
                divideAni.play(Tool.getPositionByIndex(indexFrom), Tool.getPositionByIndex(indexFrom), () => {
                    //显示
                    elementFrom.getState(StateType.HAIRBALLGREY).visible = true;
                    //都执行了
                    if (++count == countAll) callback();
                })
                // setTimeout(()=>{
                //     if (++count == countAll) callback();
                // },200)
            }
        }
    }
    private jumpAni(thisObj: PlayScene, indexs: { type: StateType, index: number }[], callback: Function) {
        let count = 0;
        let countAll = indexs.length;
        for (var a = 0; a < indexs.length; a++) {
            let data: { type: StateType, index: number } = indexs[a];
            let indexFrom = data.index;
            let elementFrom: Element = thisObj.lattices[indexFrom].element;
            let stateType: StateType = data.type;
            //判断是否能跳动
            let indexEnd = judgeActionIndex(indexFrom, thisObj.lattices);
            //有执行跳动动画
            if (indexEnd != null) {
                //去掉原先的状态
                elementFrom.setState(stateType, false);
                let elementEnd = thisObj.lattices[indexEnd].element;
                //变成毛球
                elementEnd.setState(stateType, true);
                //先隐藏
                elementEnd.getState(stateType).visible = false;

                //跳动动画
                let jumpAni: HairballJumpAni = Pool.takeOut(RecoverName.HAIRBALLJUMP_ANI)
                if (!jumpAni) jumpAni = new HairballJumpAni()
                thisObj.addChild(jumpAni);
                jumpAni.play(stateType, Tool.getPositionByIndex(indexFrom), Tool.getPositionByIndex(indexEnd), () => {
                    //显示
                    elementEnd.getState(stateType).visible = true;
                    //都执行了
                    if (++count == countAll) callback();
                })
            }
            //没有则计数
            else {
                if (++count == countAll) callback();
            }
        }
    }
    private awakeAni(thisObj: PlayScene, indexs: number[], callback: Function) {
        let count = 0;
        let countAll = indexs.length;
        for (var a = 0; a < indexs.length; a++) {
            let indexFrom = indexs[a];
            let elementFrom: Element = thisObj.lattices[indexFrom].element;
            //唤醒的动画直接写在自己的blackState里吧，然后换图
            setTimeout(() => {
                //都执行了
                if (++count == countAll) callback();
            }, 200);
        }
    }
}

/**
 * 判断果冻是否存在
 * @param lattices
 * @return false表示不存在，true表示存在
 */
function judgeJellyExist(lattices: Lattice[]) {
    for (var i = 0; i < lattices.length; i++) {
        var lattice = lattices[i]
        //没有格子或没有元素或不是果冻 跳过
        if (!lattice || !lattice.element || lattice.element.type != ElementType.JELLY) continue
        return true
    }
    return false;
}
/**
 * 判断毛球是否存在，甭管什么毛球
 * @param lattices
 */
function judgeHairballExist(lattices: Lattice[]) {
    for (var i = 0; i < lattices.length; i++) {
        var lattice = lattices[i]
        //必须是基础元素，然后判断状态毛球，有一个就返回true
        if (Tool.judgeBaseEle(lattice) &&
            (
                lattice.element.hasState(StateType.HAIRBALLGREY) ||
                lattice.element.hasState(StateType.HAIRBALLBLACK) ||
                lattice.element.hasState(StateType.HAIRBALLBROWN)
            )
        ) return true
    }
    return false;
}
function judgeFesEleBigExist(lattices: Lattice[]) {
    for (var i = 0; i < lattices.length; i++) {
        var lattice = lattices[i]
        if (lattice &&
            lattice.element &&
            lattice.element.type == ElementType.FESTIVALELE_BIG
        ) return true
    }
    return false;
}

/**
 * 判断气泡是否存在，废弃了，气泡会再生，提前判断无意义
 * @param lattices
 */
function judgeBubbleExist(lattices: Lattice[]) {
    for (var i = 0; i < lattices.length; i++) {
        var lattice = lattices[i]
        //必须是基础元素，然后判断状态气泡，有一个就返回true
        if (Tool.judgeBaseEle(lattice) && lattice.element.hasState(StateType.BUBBLE)) return true
    }
    return false;
}
/**
 * 获取所有鸡蛋的索引
 * @param lattices
 * @return
 */
function getEggs(lattices: Lattice[]) {
    var arr = [];
    for (var i = 0; i < lattices.length; i++) {
        var lattice = lattices[i]
        if (lattice &&
            lattice.element &&
            lattice.element.type == ElementType.CHICKEN_EGG
        ) {
            arr.push(i)
        }
    }
    return arr;
}
/**
 * 获取所有石门的索引
 * @param lattices
 * @return
 */
function getDoors(lattices: Lattice[]): number[] {
    var arr: number[] = [];
    for (var i = 0; i < lattices.length; i++) {
        var lattice = lattices[i]
        if (lattice &&
            lattice.door
        ) {
            arr.push(i)
        }
    }
    return arr;
}

/**
 * 判断可蔓延的方向，并返回蔓延终点的格子索引
 * 判断可分裂的方向，并返回分裂终点的格子索引
 * 判断可跳动的方向，并返回跳动终点的格子索引
 *
 * 4个方向随机，
 * 得是基础元素，且无任何状态，可以有特效，且石门非关闭
 * @param index
 * @return 没有返回null，注意判断时可能有0
 */
function judgeActionIndex(index: number, lattices: Lattice[]): number {
    //四个方向尽量随机
    var arr = [index - Tool.colNum, index + Tool.colNum];
    var rc = Tool.indexToRc(index);
    var col = rc[1];
    //列数大于0才可能有左边格子
    if (col > 0) arr.push(index - 1);
    //列数不为最右边
    if (col < Tool.colNum - 1) arr.push(index + 1);
    while (arr.length) {
        var rand = Math.floor(Math.random() * arr.length);
        var i = arr.splice(rand, 1)[0];
        if (Tool.judgeAiActionDirection(lattices[i])) return i;
    }
    return null
}
/**
 * 获得气泡变化类型
 * @param index 变化的格子索引
 * @param lattices 所有格子
 * @param baseElementTypes 可选基础类型
 */
function getBubbleType(index: number, lattices: Lattice[], baseElementTypes: number[]): ElementType {
    //变色，只取基础类型
    var rc = Tool.indexToRc(index);
    var arr = baseElementTypes.slice();
    //先去掉自己的
    Tool.removeEle(lattices[index].element.type, arr);

    let operation = (lat1: Lattice, lat2: Lattice) => {
        //必须是都可匹配的
        if (Tool.judgeMatch(lat1) &&
            Tool.judgeMatch(lat2) &&
            lat1.element.type == lat2.element.type) {
            Tool.removeEle(lat1.element.type, arr);
        }
    }
    //和左边两个比较
    if (rc[1] > 1) operation(lattices[index - 1], lattices[index - 2])
    //和上边两个比较
    if (rc[0] > 1) operation(lattices[index - Tool.colNum], lattices[index - Tool.colNum * 2])
    //下面的比较都要忽略因为顺序从小到大，所以忽略带气泡状态的，
    //与左右边两个比较，不能是第一列和最后一列
    if (rc[1] > 0 && rc[1] < Tool.colNum - 1) {
        let lat1 = lattices[index - 1];
        let lat2 = lattices[index + 1];
        //右边的格子，不能有气泡，有气泡就不用去判断了
        if (Tool.judgeMatch(lat2) && !lat2.element.hasState(StateType.BUBBLE)) operation(lat1, lat2)
    }
    //与上下两个比较，不能是第一行和最后一行
    if (rc[0] > 0 && rc[0] < Tool.rowNum - 1) {
        let lat1 = lattices[index - Tool.colNum];
        let lat2 = lattices[index + Tool.colNum];
        //下边的格子，不能有气泡，有气泡就不用去判断了
        if (Tool.judgeMatch(lat2) && !lat2.element.hasState(StateType.BUBBLE)) operation(lat1, lat2)
    }

    //右二或下二的判断操作
    let operationAdd = (lat1: Lattice, lat2: Lattice) => {
        if (Tool.judgeMatch(lat1) &&
            Tool.judgeMatch(lat2) &&
            !lat1.element.hasState(StateType.BUBBLE) &&
            !lat2.element.hasState(StateType.BUBBLE) &&
            lat1.element.type == lat2.element.type) {
            Tool.removeEle(lat1.element.type, arr);
        }
    }

    //与右边两个比较
    if (rc[1] < Tool.colNum - 2) operationAdd(lattices[index + 1], lattices[index + 2]);

    //与下边两个比较
    if (rc[0] < Tool.colNum - 2) operationAdd(lattices[index + Tool.colNum], lattices[index + Tool.colNum * 2]);

    //如果没有可选，返回自身的类型，动画还是要放的
    if (!arr.length) return lattices[index].element.type;
    //随机一个
    return Tool.randomT(arr);
}






