import { ElementType, FiveBaseElementTypes } from "../enum/ElementType";
import { EffectType } from "../enum/EffectType";
import { Pool } from "../Pool";
import { RecoverName } from "../enum/RecoverName";
import { MagicLionBgAni } from "../periodAni/MagicLionBgAni";
import { HorizontalBgAni } from "../periodAni/HorizontalBgAni";
import { VerticalBgAni } from "../periodAni/VerticalBgAni";
import { ExplosiveBgAni } from "../periodAni/ExplosiveBgAni";
import { ChickenEgg } from "./ChickenEgg";
import { State } from "./State";
import { stateDatas, StateType } from "../enum/StateType";
import { Tool } from "../Tool";
import { FestivalEle } from "./FestivalEle";
import { RES } from "../../../module/RES";


/**
 * 考虑到底继承白鹭的啥Component还是Container
 * 坐标原点需要坐落在格子的中心点
 * 最好到时按，底图，动效，气泡，笼子，毛球，进行分层，如果多个状态要共存时，必须分层，到时气泡的动画，要写再自己的层里
 */
export class Element extends FYGE.Container {
    /**
     * 初始类型
     */
    private _type: ElementType;
    get type() {
        return this._type
    }
    /**
     * 显示的内容，暂时统一为FrameAni先，到时，鸡蛋等等都放这，统一为显示用，
     */
    private showImage: FYGE.FrameAni;
    /**
     * 临时记录特效使用
     */
    temEffectType: EffectType = null;
    /**
     * 特效类型
     */
    private _effectType: EffectType = null;
    get effectType() {
        return this._effectType;
    }
    set effectType(value: EffectType) {
        if (this._effectType == value) return
        if (value != null) {
            //先去掉原先有的
            this.removeEffectHas();
            //赋值现在的
            switch (value) {
                case EffectType.MAGICLION:
                    //添加MagicLionBgAni
                    this.magicLionBgAni = Pool.takeOut(RecoverName.MAGICLIONBG_ANI)
                    if (!this.magicLionBgAni) {
                        this.magicLionBgAni = new MagicLionBgAni();
                    } else {
                        this.magicLionBgAni.reset();
                    }
                    this.addChildAt(this.magicLionBgAni, 0);
                    break;
                case EffectType.HORIZONTAL:
                    //添加HorizontalBgAni
                    this.horizontalBgAni = Pool.takeOut(RecoverName.HORIZONTALBG_ANI)
                    if (!this.horizontalBgAni) {
                        this.horizontalBgAni = new HorizontalBgAni();
                    } else {
                        this.horizontalBgAni.reset();
                    }
                    this.addChildAt(this.horizontalBgAni, 1)
                    break;
                case EffectType.VERTICAL:
                    //添加VerticalBgAni
                    this.verticalBgAni = Pool.takeOut(RecoverName.VERTICALBG_ANI)
                    if (!this.verticalBgAni) {
                        this.verticalBgAni = new VerticalBgAni();
                    } else {
                        this.verticalBgAni.reset();
                    }
                    this.addChildAt(this.verticalBgAni, 1)
                    break;
                case EffectType.EXPLOSIVE:
                    this.explosiveBgAni = Pool.takeOut(RecoverName.EXPLOSIVEBG_ANI)
                    if (!this.explosiveBgAni) {
                        this.explosiveBgAni = new ExplosiveBgAni();
                    } else {
                        this.explosiveBgAni.play(0);
                    }
                    this.addChildAt(this.explosiveBgAni, 1)
                    break;
            }
            this._effectType = value;
        } else {
            //回收掉原先有的
            this.removeEffectHas();
            this._effectType = null;
        }
        //修改显示
        this.changeSource();
    }
    private magicLionBgAni: MagicLionBgAni;
    private horizontalBgAni: HorizontalBgAni;
    private verticalBgAni: VerticalBgAni;
    private explosiveBgAni: ExplosiveBgAni;
    /**
     * 索引
     */
    index: number
    /**
     * 第几行
     */
    row: number;
    /**
     * 第几列
     */
    column: number
    //鸡蛋
    chickenEgg: ChickenEgg;
    //节日红包大
    festivalEle: FestivalEle;

    /**
     * 所有的状态，注意，变色气泡特殊，不能和特效共存，所以初始化时，气泡的不能加特效。生成特效，去掉气泡
     * 索引必须按StateType的枚举
     */
    private states: State[] = []

    /**
     *
     * @param type 只应该是基础元素和特殊元素
     */
    constructor(type: ElementType) {
        super();
        this._type = type;
        this.changeSource();
        //鸡蛋
        if (type == ElementType.CHICKEN_EGG) {
            this.chickenEgg = Pool.takeOut(RecoverName.CHICKEN_EGG)
            if (!this.chickenEgg) {
                this.chickenEgg = new ChickenEgg();
            } else {
                this.chickenEgg.reset();
            }
            this.addChild(this.chickenEgg)
        }
        //节日红包
        else if (type == ElementType.FESTIVALELE_BIG) {
            this.festivalEle = Pool.takeOut(RecoverName.FESTIVAL_ELE)
            if (!this.festivalEle) {
                this.festivalEle = new FestivalEle();
            } else {
                this.festivalEle.reset();
            }
            this.addChild(this.festivalEle)
        }

    }

    moveCount = 0; // 移动计数
    moveDir = 1; // 移动方向
    moveDis = 1; // 移动距离
    moveMaxDis = 4; // 最大移动距离
    moveFrame = 0;  // 移动了几帧
    moveFrameSign = 6;  // 要几帧

    update() {
        super.update();

        if (
            this._effectType == EffectType.HORIZONTAL
            || this._effectType == EffectType.VERTICAL
        ) {
            this.moveFrame++;
            if (this.moveFrame > this.moveFrameSign) {
                this.moveFrame = 0;
                this.moveCount += this.moveDir * this.moveDis;
            }

            const xy = (this._effectType == EffectType.HORIZONTAL) ? "x" : "y";
            this[xy] += this.moveDir * this.moveDis / this.moveFrameSign;
            if (Math.abs(this.moveCount) >= this.moveMaxDis) {
                this.moveDir *= -1;
            }
        }
    }


    /**
     * 类型和特效类型得提前赋值
     * 暂时为，修改贴图
     * 只用于修改显示
     * 不包括state的逻辑
     */
    private changeSource() {
        var texArr: FYGE.Texture[];
        //如果不带特效，暂时都是静态图，都会是"ele"+this._type+".png"的格式
        if (this._effectType == null) {
            texArr = [RES.getRes("ele" + this._type + ".png")];
        }
        //带特效的，
        else {
            if (this._effectType == EffectType.EXPLOSIVE) {
                texArr = [RES.getRes("ele" + this._type + "Exp.png")];
            }
            else if (this._effectType == EffectType.MAGICLION) {
                texArr = [RES.getRes("magicLion.png")];
            } else {
                //直线特效的 hor ver
                // texArr = [];
                // var hv = this._effectType == EffectType.HORIZONTAL ? "hor" : "ver";
                // for (var i = 0; i <= 15; i++) {
                //     texArr.push(RES.getRes(hv + "_ele" + this._type + "_" + i + ".png"));
                // }
                // for (var i = 14; i >= 1; i--) {
                //     texArr.push(RES.getRes(hv + "_ele" + this._type + "_" + i + ".png"));
                // }
                texArr = [RES.getRes("ele" + this._type + "Hor.png")];
            }
        }
        //处理showImage
        if (!this.showImage) {
            this.showImage = this.addChild(new FYGE.FrameAni(texArr));
        } else {
            this.showImage.resetTexturesAll(texArr)
        }
        //单张贴图的都reset(0)
        if (this.showImage.totalFrames == 1) {
            this.showImage.reset(0);
        }
        //其他的循环序列帧
        else {
            this.showImage.play(0);
        }
        //要变透明的，鸡蛋和节日，魔力鸟特效
        if (this._type == ElementType.CHICKEN_EGG ||
            this._type == ElementType.FESTIVALELE_BIG ||
            this._effectType == EffectType.MAGICLION
        ) {
            this.showImage.alpha = 0;
        } else {
            this.showImage.alpha = 1;
        }
        //爆炸特效式加动效
        if (this._effectType == EffectType.EXPLOSIVE) this.explosiveTween();
    }

    /**
     * 会重置掉所有特效类型，枷锁，鸡蛋等
     * @param type  只应该是基础元素和特殊元素
     */
    reset(type: ElementType) {
        this.alpha = this.scaleX = this.scaleY = 1;
        //类型重置，showImage修改
        this._type = type;
        //特效重置
        this.effectType = null;
        this.temEffectType = null;
        //类型和特效确定后
        this.changeSource();
        //所有状态重置
        this.removeAllState();
        //如果类型是鸡蛋
        if (type == ElementType.CHICKEN_EGG) {
            this.chickenEgg = this.chickenEgg || Pool.takeOut(RecoverName.CHICKEN_EGG)
            if (!this.chickenEgg) {
                //新建
                this.chickenEgg = new ChickenEgg();
            } else {
                this.chickenEgg.reset();
            }
            this.addChild(this.chickenEgg)
        }
        else if (this.chickenEgg) {
            this.removeChild(this.chickenEgg);
            Pool.recover(RecoverName.CHICKEN_EGG, this.chickenEgg);
            this.chickenEgg = null;
        }
        //如果类型是节日红包大
        if (type == ElementType.FESTIVALELE_BIG) {
            this.festivalEle = this.festivalEle || Pool.takeOut(RecoverName.FESTIVAL_ELE)
            if (!this.festivalEle) {
                //新建
                this.festivalEle = new FestivalEle();
            } else {
                this.festivalEle.reset();
            }
            this.addChild(this.festivalEle)
        } else if (this.festivalEle) {
            this.removeChild(this.festivalEle);
            Pool.recover(RecoverName.FESTIVAL_ELE, this.festivalEle);
            this.festivalEle = null;
        }
    }

    /**
     * 只修改类型，不改变其他状态，主要针对修改基础元素类型
     * @param type
     */
    resetType(type: ElementType) {
        //如果类型一致，return
        if (this._type == type) return
        //如果目标类型不是基础元素 或者原先不是基础元素
        if (FiveBaseElementTypes.indexOf(type) == -1 ||
            FiveBaseElementTypes.indexOf(this._type) == -1
        ) {
            this.reset(type)
        } else {
            this._type = type;
            this.changeSource();
            //如果有气泡状态,气泡也要变成相应的
            if (this.hasState(StateType.BUBBLE)) {
                this.getState(StateType.BUBBLE).reset(type);
                //一样要隐藏showImage
                this.showImage.alpha = 0;
            }
        }
    }

    /**
     * 去掉原先带的所有特效
     */
    private removeEffectHas() {
        //回收掉原先有的
        switch (this._effectType) {
            case EffectType.MAGICLION:
                this.removeChild(this.magicLionBgAni);
                Pool.recover(RecoverName.MAGICLIONBG_ANI, this.magicLionBgAni);
                this.magicLionBgAni = null;
                break;
            case EffectType.HORIZONTAL:
                this.removeChild(this.horizontalBgAni);
                Pool.recover(RecoverName.HORIZONTALBG_ANI, this.horizontalBgAni);
                this.horizontalBgAni = null;
                break;
            case EffectType.VERTICAL:
                this.removeChild(this.verticalBgAni);
                Pool.recover(RecoverName.VERTICALBG_ANI, this.verticalBgAni);
                this.verticalBgAni = null;
                break;
            case EffectType.EXPLOSIVE:
                this.removeChild(this.explosiveBgAni);
                Pool.recover(RecoverName.EXPLOSIVEBG_ANI, this.explosiveBgAni);
                FYGE.Tween.removeTweens(this.explosiveBgAni);
                FYGE.Tween.removeTweens(this.showImage);
                this.explosiveBgAni = null;
                break;
        }
    }

    public fallAni() {
        // FYGE.Tween.get(this, null, null, true)
        //     .set({ scaleY: 1 })
        //     .to({ scaleY: 0.7 }, 200)
        //     .to({ scaleY: 1 }, 100)
        let oriY = this.y;
        FYGE.Tween.get(this, null, null, true)
            .to({ y: oriY+4 }, 100)
            .to({y: oriY }, 100)
    }

    /**
     * 是否有该状态
     * @param state
     */
    hasState(state: StateType): boolean {
        return !!this.states[state];
    }

    /**
     * 设置状态
     * @param state 状态类型
     * @param set true为设置
     */
    setState(state: StateType, set: boolean, data?: any) {
        //set为false的话，
        if (!set) {
            //如果原先有状态，去掉
            if (this.hasState(state)) {
                //自己回收,动画，然后从父级移除，最后进入pool
                this.states[state].recover();
                //置空
                this.states[state] = null;
                //如果状态是气泡，并且特效不是魔力鸟时，显示showImage，魔力鸟显示原图
                if (state == StateType.BUBBLE && this.effectType != EffectType.MAGICLION) this.showImage.alpha = 1;
            }
            //原先每状态不管
            else {
            }
        }
        //set为true的话
        else {
            //如果有状态，执行重置
            if (this.hasState(state)) {
                this.states[state].reset(data);
            }
            //没有的话加上
            else {
                var stateData = stateDatas[state];
                var recoverName: RecoverName = stateData.recoverName;
                var className = stateData.className;
                let stateEx = Pool.takeOut(recoverName);
                if (!stateEx) {
                    stateEx = new className(data);
                } else {
                    stateEx.reset(data)
                }
                this.states[state] = stateEx;
                //视图添加
                this.addChild(this.states[state]);
                //气泡定制逻辑，暂时没出现给特效元素设置气泡的操作，所以先不管，只对视图做简单处理
                if (state === StateType.BUBBLE) this.showImage.alpha = 0;
            }
        }
    }


    /**
     * 判断是否有任何特效，true表示有，false表示没有
     */
    hasAnyState(): boolean {
        for (var i = 0; i < this.states.length; i++) {
            if (this.states[i]) return true
        }
        return false
    }
    /**
     * 去掉所有状态
     */
    removeAllState() {
        for (var i = 0; i < this.states.length; i++) {
            let state = this.states[i];
            if (!state) continue
            //直接移除
            this.removeChild(state);
            //直接回收
            Pool.recover(stateDatas[i].recoverName, state);
            //置空
            this.states[i] = null;
        }
    }
    /**
     * 取得一个状态
     * @param state
     */
    getState(state: StateType): any {
        return this.states[state]
    }

    /**
     * 克隆一个
     * 类型
     * 特效
     * 状态
     * 位置
     */
    clone(): Element {
        let ele = Tool.getElement(this.type);
        //特效加上
        ele.effectType = this.effectType;
        //状态加上
        for (var i = 0; i < this.states.length; i++) {
            let state = this.states[i];
            if (!state) continue;
            ele.setState(i, true, this.type)
        }
        //位置信息
        ele.x = this.x;
        ele.y = this.y;
        return ele
    }

    /**
     * 暂时给石门关闭的元素用的
     * 拷贝另一个元素的
     * 类型
     * 特效
     * 状态
     */
    copy(ele: Element) {
        //类型重置
        this.reset(ele.type);
        //特效加上
        this.effectType = ele.effectType;
        //状态加上
        for (var i = 0; i < ele.states.length; i++) {
            let state = ele.states[i];
            if (!state) continue;
            ele.setState(i, true, ele.type)
        }
    }

    /**
     * 这爆炸是的动效
     */
    private explosiveTween() {
        if (!this.explosiveBgAni) return;
        [this.explosiveBgAni, this.showImage].forEach((e) => {
            e.y = 0;
            e.scaleY = 1;
            FYGE.Tween.get(e, { loop: true })
                .to({ y: -2 }, 100)
                .to({ y: 4 }, 200)
                .to({ y: 0 }, 200)
                .to({ y: -2 }, 100)
                .to({ y: 4 }, 200)
                .to({ y: 0 }, 200)
                .wait(1000);
            FYGE.Tween.get(e, { loop: true })
                .to({ scaleY: 0.95 }, 100)
                .to({ scaleY: 1 }, 100)
                .wait(300)
                .to({ scaleY: 0.95 }, 100)
                .to({ scaleY: 1 }, 100)
                .wait(1300)
        })

    }
}

//添加一个重置所有贴图的方法，到时加到引擎里，可以注掉了
FYGE.FrameAni.prototype.resetTexturesAll = function (texturesAll: FYGE.Texture[]) {
    this.texturesAll = texturesAll;
    // this.changeTexture(0);
    this.currentFrame = 0;
    this.frameRate = 30;
}
