import { MapConf } from "../conf/MapConf";
import { BattleUtil } from "./BattleUtil";
import { BuffData, BuffDataPool } from "./BuffData";
import { BulletData, BulletDataPool } from "./BulletData";
import { DataBase } from "./DataBase";
import { EnemyData, EnemyDataPool } from "./EnemyData";
import { HeroData, HeroDataPool } from "./HeroData";

//英雄站位
export interface PosData {
    hero: HeroData,
    posID: number,
    pos: BattleUtil.Vector2
}

export interface EnemyBornData {
    
    bornTime: number,
    positionID: number,
    typeID: number,
    level: number,
    roldID: number
}

//地图格子 单例
export class MapData {
    protected static instance:MapData;
//-------------------配置数据----------------------
    //所属类型编号
    typeID: number;
    //地图格子数量,目前固定是10*10
    size:BattleUtil.Vector2;
    //每个格子大小
   // sizeUnit:BattleUtil.Vector2;
    //格子数量
    length:number;
    //每个格子的坐标 从左下角开始
    /**
     * 90 91 92 93 94 95 96 97 98 99
     * 80 81 82 83 84 85 86 87 88 89
     * 70 71 72 73 74 75 76 77 78 79
     * 60 61 62 63 64 65 66 67 68 69
     * 50 51 52 53 54 55 56 57 58 59
     * 40 41 42 43 44 45 46 47 48 49
     * 30 31 32 33 34 35 36 37 38 39
     * 20 21 22 23 24 25 26 27 28 29
     * 10 11 12 13 14 15 16 17 18 19
     * 0  1  2  3  4  5  6  7  8  9
     */
    //pointList:Array<Array<number>>;
    //常规路径
    normalRold:Array<Array<number>>;
    //特殊路径
    // //捷径 至少有3个点:起点,终点,中间点,其中起点和终点是常规路径上的点
    // shortcut:Array<Array<number>>;

    //终点
    endPosition:number;
    //攻击点
    attackPosition:Array<number>;
    //敌人出生列表
    enemyBornMap:Map<number,Array<EnemyBornData>> = new Map();
    //出生时长
    bornNeedTime:number = 0;

//-------------------动态数据----------------------
    // 攻击位<>
	attackPosDataMap: Map<number,PosData> = new Map();
    //所有存活的敌人
    enemyDataList:Array<EnemyData> = []
    //所有子弹
    bulletList:Array<BulletData> = []

    buffMap: Map<number,BuffData> = new Map();

    //地图点对应坐标坐标
    mapPosList:Array<BattleUtil.Vector2> = []

    //当前帧
    curTurn:number = 0;
    //游戏是否结束
    protected _battleEnd:boolean = false;
    protected _bWin:boolean = false;

    //操作列表  number表示帧数
    actionMap:Map<number,Array<BattleUtil.HeroDataChange>> = new Map();
    
    static GetInstance():MapData{
        if(!MapData.instance){
            MapData.instance = new MapData();
        }
        return MapData.instance;
    }
    //析构
    static Dispose(){
        MapData.instance = null;
    }

    set bWin(b:boolean){
        this._bWin = b;
    }
    get bWin():boolean{
        return this._bWin;
    }
    set battleEnd(b:boolean){
        this._battleEnd = b;
        if(b){
            this.bWin = this.enemyDataList.length == 0;
            let  str:string = JSON.stringify(Object.fromEntries(this.actionMap))
            console.log(str)
            
        }
    }
    get battleEnd():boolean{
        return this._battleEnd;
    }
    
    init(typeID:number){

        this.typeID = typeID;
        this.size = new BattleUtil.Vector2(10,10);
        //this.sizeUnit = new BattleUtil.Vector2(70,70);
        this.length = this.size.x*this.size.y;

        for(let i = 0; i < this.length; i++){
            this.mapPosList.push(this.getPosition(i))
        }
        // for(let i=0;i<this.length;i++){
        //     this.pointList[i] = [];
        // }

        //读表
        this.normalRold = MapConf.data[typeID.toString()].RoldJsonArr;

        this.endPosition = this.normalRold[0][this.normalRold[0].length-1];
        this.attackPosition = MapConf.data[typeID.toString()].AttackPositionArray;

        let EnemyJsonArr = MapConf.data[typeID.toString()].EnemyJsonArr;
        EnemyJsonArr.forEach((enemyObj)=>{
            if(enemyObj.length < 7) return;
            for(let j=0;j<enemyObj[5];j++){
                let enemyBornData:EnemyBornData = {
                    bornTime: enemyObj[0] + enemyObj[6]*j,
                    positionID: enemyObj[1],
                    typeID: enemyObj[2],
                    level: enemyObj[3],
                    roldID: enemyObj[4]
                }
                if(this.enemyBornMap.has(enemyBornData.bornTime)){
                    this.enemyBornMap.get(enemyBornData.bornTime).push(enemyBornData);
                }else{
                    if(this.bornNeedTime < enemyBornData.bornTime){
                        this.bornNeedTime = enemyBornData.bornTime;
                    }
                    this.enemyBornMap.set(enemyBornData.bornTime,[enemyBornData]);
                }
            }
            
        })

        this.attackPosDataMap.clear()
        this.attackPosition.forEach((v,k)=>{
            //this.pointList[pos.x][pos.y] = 1;
            let podID = Number(v)
            let posData:PosData = {
                hero: null,
                posID: podID,
                pos: this.getPosition(podID)
            }


            this.attackPosDataMap.set(v,posData);

        })

        this.curTurn = 0;
        //游戏是否结束
        this._battleEnd = false;
        this._bWin = false;
        
    }

    reset(typeID:number){

        this.typeID = typeID;

        this.attackPosDataMap.clear();
        //所有存活的敌人
        this.enemyDataList.splice(0,this.enemyDataList.length);
        //所有子弹
        this.bulletList.splice(0,this.bulletList.length);
    
        this.buffMap.clear();
    
        
        //操作列表  number表示帧数
        this.actionMap.clear();
        console.log("clear!")


        //读表
        this.normalRold = MapConf.data[typeID.toString()].RoldJsonArr;

        this.endPosition = this.normalRold[0][this.normalRold[0].length-1];
        this.attackPosition = MapConf.data[typeID.toString()].AttackPositionArray;

        this.enemyBornMap.clear();
        let EnemyJsonArr = MapConf.data[typeID.toString()].EnemyJsonArr;
        EnemyJsonArr.forEach((enemyObj)=>{
            if(enemyObj.length < 7) return;
            for(let j=0;j<enemyObj[5];j++){
                let enemyBornData:EnemyBornData = {
                    bornTime: enemyObj[0] + enemyObj[6]*j,
                    positionID: enemyObj[1],
                    typeID: enemyObj[2],
                    level: enemyObj[3],
                    roldID: enemyObj[4]
                }
                if(this.enemyBornMap.has(enemyBornData.bornTime)){
                    this.enemyBornMap.get(enemyBornData.bornTime).push(enemyBornData);
                }else{
                    if(this.bornNeedTime < enemyBornData.bornTime){
                        this.bornNeedTime = enemyBornData.bornTime;
                    }
                    this.enemyBornMap.set(enemyBornData.bornTime,[enemyBornData]);
                }
            }
            
        })

        this.attackPosDataMap.clear()
        this.attackPosition.forEach((v,k)=>{
            //this.pointList[pos.x][pos.y] = 1;
            let podID = Number(v)
            let posData:PosData = {
                hero: null,
                posID: podID,
                pos: this.getPosition(podID)
            }


            this.attackPosDataMap.set(v,posData);

        })

        this.curTurn = 0;
        this._battleEnd = false;
        this._bWin = false;
    }
    
   getNormalRold(id:number):Array<number>{
       return this.normalRold[id%this.normalRold.length];
   }

   //根据id获取坐标 取值范围[0,this.length-1]
   getPosition(id:number):BattleUtil.Vector2{
       if(id<0 || id>=this.length) return null;
       let pos = new BattleUtil.Vector2(0,0);
       pos.x = id%this.size.x;
       pos.y = Math.floor(id/this.size.x);
       return pos;
   }

   //添加到地图上
   addHero(typeID:number,level:number,posID:number){
        let hero = HeroDataPool.getObject()
        hero.init(typeID,level,posID);
        console.log(typeof(posID),posID)
       if(this.attackPosDataMap.has(posID)){
            let posData = this.attackPosDataMap.get(posID)
            let posHero = posData.hero;
            if(posHero){
                posHero.clear();
                HeroDataPool.putObject(posHero);
            }
            posData.hero = hero
           hero.position = posData.pos;
       }
       return hero;
   }
   //移除地图上指定位置的英雄
   removeHero(posID:number){

        if(this.attackPosDataMap.has(posID)){
            let posData = this.attackPosDataMap.get(posID);
            let posHero = posData.hero;
            if(posHero){
                posHero.clear();
                HeroDataPool.putObject(posHero);
            }
            posData.hero = null;
        }
   }


   /**
    *添加敌人 
    * @param typeID 敌人类型
    * @param level 敌人等级
    * @param roldID 敌人行走路径
    * @param bronPos 敌人在路径上哪个点走
    */
   addEnemy(typeID:number,level:number,roldID:number,bronPos:number){
        let enemy = EnemyDataPool.getObject()
        let rold = this.getNormalRold(roldID);
        enemy.init(typeID,level,rold);
        this.enemyDataList.push(enemy);
        enemy.position = this.getPosition(bronPos);
        enemy.speedVector = new BattleUtil.Vector2(0,0);

        
        enemy.speedVector = this.getEnemySpeedVector(enemy);
        
        enemy.posID = bronPos;

        return enemy;
   }
   //移除地图上指定的敌人
   removeEnemy(enemy:EnemyData){
        let index = this.enemyDataList.indexOf(enemy);
        if(index>=0){
            this.enemyDataList.splice(index,1);
        }
        enemy.clear();
        EnemyDataPool.putObject(enemy);
   }

   getEnemySpeedVector(enemy:EnemyData):BattleUtil.Vector2{
        let oldPos = this.mapPosList[enemy.posID]
        let newPos = this.mapPosList[enemy.nextPosID]
        if(newPos){
            let direction = BattleUtil.Vector2.Sub(newPos,oldPos)
            direction.multiply(enemy.speedCur)
            return direction;
        }
        return new BattleUtil.Vector2(0,0);
   }

    addBuff(buffID:number,duration:number,valueList:Array<number>,src:DataBase,target:DataBase){
        let buff:BuffData = this.buffMap.get(buffID)
        if(buff == null){
            buff = BuffDataPool.getObject()
            buff.init(buffID,duration,valueList,src,target)
            this.buffMap.set(buff.ID,buff)
            if(target instanceof EnemyData){
                target.addBuff(buff)
            }
        }
        return buff;
    }

    removeBuff(ID:number){
        let buff:BuffData = this.buffMap.get(ID)
        if(buff != null){
            let target = buff.targetDataBase
            if(target instanceof EnemyData){
                target.removeBuff(buff)
            }
            buff.clear()
            BuffDataPool.putObject(buff)
            this.buffMap.delete(ID)
        }
    }

    addBullet(typeID:number,srcHero:HeroData,targetEnemy:EnemyData){
        let bullet:BulletData = BulletDataPool.getObject()
        bullet.init(typeID,srcHero,targetEnemy)
        this.bulletList.push(bullet)
        return bullet;
    }

    removeBullet(bullet:BulletData){
        let index = this.bulletList.indexOf(bullet);
        if(index>=0){
            this.bulletList.splice(index,1);
        }
        bullet.clear();
        BulletDataPool.putObject(bullet);
   }


   clear(){
        this.attackPosDataMap.forEach((posData,posID)=>{
            if(posData.hero){
                posData.hero.clear();
                HeroDataPool.putObject(posData.hero);
            }
        })
        this.attackPosDataMap.clear();
        this.enemyDataList.forEach((enemy)=>{
            enemy.clear();
            EnemyDataPool.putObject(enemy);
        })
        this.enemyDataList = [];
        // this.bulletList.forEach((bullet)=>{
        //     bullet.clear();
        //     BulletDataPool.putObject(bullet);
        // })
        // this.bulletList = [];

        this.buffMap.forEach((buff)=>{
            buff.clear();
            BuffDataPool.putObject(buff);
        })
   }

}