import { AnimationComponent, CameraComponent, director, find, GraphicsComponent, instantiate, loader, Node, Prefab, Vec3, _decorator } from 'cc';
import { EventDispatcher } from '../../../engines/events/EventDispatcher';
import { GUIManager } from '../../../engines/gui/GUIManager';
import { CameraUtils } from '../../../engines/utils/CameraUtils';
import GameConfigManager from '../../models/GameConfigManager';
import { GameModel } from '../../models/GameModel';
import { FightingScene } from '../../scenes/FightingScene';
import { UIConst } from '../UIConst';
import { FenceBase } from './fences/FenceBase';
import { FightingMediator } from './FightingMediator';
import { MonsterBase } from './monsters/MonsterBase';
import { MonsterHPUIPool } from './monsters/MonsterHPUIPool';
import { SkillBase } from './skills/SkillBase';
import SkillManager from './skills/SkillManager';
import AutomaticFifleWeapon from './weapons/AutomaticFifleWeapon';
import { SingleShotWeapon } from './weapons/SingleShotWeapon';
import { WeaponBase } from './weapons/WeaponBase';
const { ccclass, property } = _decorator;


export class GameController extends EventDispatcher{

    public weapon:WeaponBase;
    public fence:FenceBase;
    public camera:CameraComponent;

    public leftEndNode:Node;
    public middleEndNode:Node;
    public rightEndNode:Node;

    public leftStartNode:Node;
    public middleStartNode:Node;
    public rightStartNode:Node;

    /**
     * 当前正在运行的技能
     */
    public currentSkill:SkillBase;

    /**
     * 游戏结束
     */
    public GameOver:boolean=true;


    public leftMonsterList:MonsterBase[];
    public middleMonsterList:MonsterBase[];
    public rightMonsterList:MonsterBase[];

    /**
     * 怪物弹痕预制体
     */
    public monsterZhouDanPrefab:Prefab;

    /**
     * 怪物血条层
     */
    public monsterHPUILayer:Node;

    /**
     * 关卡配置
     */
    public levelConfig:any;

    private monstersConfig:any[];
    /**
     * 这一关怪物数量
     */
    public monsterTotalCount:number;

    /**
     * 本局游戏时间
     */
    private runTime:number=0;

    private fightingMediator:FightingMediator;

    constructor()
    {
        super();
        this.leftMonsterList=[];
        this.middleMonsterList=[];
        this.rightMonsterList=[];
    }

    /**
     * 初始化
     * @param leftHand
     * @param rightHand
     */
    Init(uiMediator:FightingMediator):void{
        this.fightingMediator=uiMediator;

        let sceneNode:Node=find("FightingScene");
        if(sceneNode==null){
            throw new Error("找不到战斗场景节点！");
        }
        let sceneScript:FightingScene=sceneNode.getComponent(FightingScene);
        if(sceneNode==null){
            throw new Error("战斗场景上没有挂载FightingScene脚本！");
        }
        this.camera=sceneScript.camrea;

        this.leftStartNode=sceneScript.LeftStartPos;
        this.middleStartNode=sceneScript.MiddleStartPos;
        this.rightStartNode=sceneScript.RightStartPos;

        this.leftEndNode=sceneScript.LeftEndPos;
        this.middleEndNode=sceneScript.MiddleEndPos;
        this.rightEndNode=sceneScript.RightEndPos;

        this.monsterZhouDanPrefab=sceneScript.monsterZhouDanPrefab;

        this.weapon=this.CreateWeapon(sceneScript.leftHand,sceneScript.rightHand);
        this.StartGame();
    }

    /**
     * 初始化栅栏
     */
    private InitFence():void{
        //如果老的存在，先清理
        if(this.fence&&this.fence.node!=null){
            this.fence.node.destroy();
            this.fence=null;
        }
        let config:any=GameConfigManager.GetFenceConfig(GameModel.single.fenceId);
        let prefab:Prefab=loader.getRes(config.prefab);
        if(prefab==null){
            throw new Error("栅栏资源未加载！");
        }
        let fenceNode:Node=instantiate(prefab);
        this.fence=fenceNode.getComponent(FenceBase);
        this.fence.config=config;
        this.fence.node.setPosition(new Vec3(0,0,-2));
        this.scene.addChild(fenceNode);
    }

    /**
     * 开始游戏
     */
    StartGame():void{
        GameModel.single.killCount=0;
        GameModel.single.angerCount=0;
        GameModel.single.integral=0;
        //重置技能
        this.SkillReset();
        this.levelConfig=GameConfigManager.GetLevelConfig(GameModel.single.currentLevel);
        this.runTime=0;
        //复制一份配置
        this.monstersConfig=GameConfigManager.CreateMonsterByList(this.levelConfig.monsters,this.runTime);
        this.monsterTotalCount=this.monstersConfig.length;
        //直接重置子弹数量
        this.weapon.bulletCount=GameConfigManager.GetWeaponConfig(GameModel.single.currentWeaponId).clip;
        //初始化栅栏
        this.InitFence();
        this.GameOver=false;
        this.paused=false;
    }

    /**
     * 游戏结束
     * @param state 0 胜利 1 失败 2正常退出
     */
    OnGameOver(state:number):void{
        //清理怪物
        this.ClearMonsters();
        //清理武器
        this.weapon.Destroy();
        //销毁栅栏
        if(this.fence.node){
            this.fence.node.destroy();
        }
        if(state==0){
            GUIManager.single.Show(UIConst.GAME_OVER_UI,true);
        }else if(state==1)
        {
            GUIManager.single.Show(UIConst.GAME_OVER_UI,false);
        }
        GUIManager.single.Hide(UIConst.FIGHTING_UI);
        this.GameOver=true;
    }

    paused:boolean;
    /**
     * 暂停游戏
     */
    PauseGame():void{
        this.paused=true;
    }

    /**
     * 继续游戏
     */
    PlayGame():void{
        this.paused=false;
    }

    /**
     * 重玩
     */
    Replay():void{
        this.StartGame();
        GUIManager.single.Show(UIConst.FIGHTING_UI);
    }

    /**
     * 开始下一关
     */
    PlayNextLevel():void{
        //清空试用栅栏
        GameModel.single.trialFenceId=-1;
        console.log(GameModel.single.currentLevel);
        this.StartGame();
        GUIManager.single.Show(UIConst.FIGHTING_UI);
    }

    /**
     * 清理怪物
     */
    ClearMonsters():void{
        this.clearMonsterList(this.leftMonsterList);
        this.clearMonsterList(this.middleMonsterList);
        this.clearMonsterList(this.rightMonsterList);
    }

    private clearMonsterList(list:MonsterBase[]):void{
        if(list.length>0){
            list.forEach(element => {
                if(element.node!=null&&element.node.isValid){
                    element.node.destroy();
                }
            });
        }
        list.length=0;
    }

    TryFire(fireKey:number):void{
        if(this.currentSkill!=null&&this.currentSkill.unController){
            return;
        }
        if(fireKey==0){
            this.weapon.StopFire();
        }else{
            this.weapon.StartFire(fireKey);
        }
    }

    /**
     * 使用技能
     */
    UseSkill():void{
        if(this.currentSkill!=null){
            return;
        }
        //重置子弹数量
        this.weapon.bulletCount=this.weapon.maxBulletCount;
        
        this.currentSkill=SkillManager.single.Create(this.weapon.weaponConfig.skill);
        this.currentSkill.config=GameConfigManager.GetSkillConfig(this.weapon.weaponConfig.skill);
        this.currentSkill.AddEvent(SkillBase.SKILL_COMPLETE,this,this.SkillReset,0);
        this.currentSkill.UseSkill(this.weapon,this);
        GameModel.single.angerCount=0;
    }

    /**
     * 清除技能
     */
    private SkillReset():void{
        if(this.currentSkill!=null){
            this.currentSkill.RemoveEvent(SkillBase.SKILL_COMPLETE,this,this.SkillReset);
            this.currentSkill.Dispose();
            this.currentSkill=null;
        }
    }

    Update(dt:number):void{
        if(this.paused){
            return;
        }
        if(this.GameOver){
            return;
        }
        if(this.currentSkill!=null){
            this.currentSkill.Update(dt);
        }
        this.runTime+=dt*1000;
        this.weapon.Update(dt);
        this.CheckMonster();
    }

    get drawingBoard():GraphicsComponent{
        return this.fightingMediator.DrawingBoard;
    }
    
    /**
     * 检测怪物
     */
    CheckMonster():void{
        if(this.monstersConfig.length>0){
            let config:any;
            let monster:Node;
            for (let index = 0; index < this.monstersConfig.length; index++) {
                config = this.monstersConfig[index];
                if(this.runTime>=config.createTime){
                    //根据配置创建怪物
                    monster=this.CreateMonster(config);
                    this.scene.addChild(monster);
                    this.monstersConfig.splice(index,1);
                    index--;
                }
            }
        }
        if(this.monstersConfig.length==0&&this.leftMonsterList.length==0&&this.middleMonsterList.length==0&&this.rightMonsterList.length==0){
            //全部怪物死亡
            console.log("通关");
            GameModel.single.currentLevel++;
            if(GameModel.single.currentLevel>=GameConfigManager.MaxLevel){
                GameModel.single.currentLevel=GameConfigManager.MaxLevel;
            }
            this.OnGameOver(0);
        }
    }
    
    /**
     * 怪物攻击
     * @param damage 伤害 
     */
    MonsterAttack(attackType:number,damage:number):void{
        if(this.GameOver){
            return;
        }
        if(attackType==0){
            if(this.fence.IsDie==false){
                this.fence.Damage(damage);
                let cameraUtils:CameraUtils=this.camera.getComponent(CameraUtils);
                if(cameraUtils!=null){
                    cameraUtils.shake(500,new Vec3(-0.01,-0.01,0),new Vec3(0.01,0.01,0));
                }
            }
        }else{
            this.OnGameOver(1);
        }
    }

    /**
     * 是否有怪物可攻击 -1没有可攻击怪 0 左边 1中间 2右边
     */
    public get FindAttackMonsterPosType():number{
        let leftDis:number=this.NearestDistance(this.leftMonsterList);
        let middleDis:number=this.NearestDistance(this.middleMonsterList);
        let rightDis:number=this.NearestDistance(this.rightMonsterList);
        if(leftDis<middleDis&&leftDis<rightDis){
            return 0;
        }
        if(middleDis<leftDis&&middleDis<rightDis){
            return 1;
        }
        if(rightDis<leftDis&&rightDis<middleDis){
            return 2;
        }
        return -1;
    }

    /**
     * 就算这一路中可攻击怪的最近距离
     * @param monsterList 
     */
    private NearestDistance(monsterList:MonsterBase[]):number{
        let monster:MonsterBase;
        let endNode:Node;
        let minDis:number=Number.MAX_VALUE;
        let dis:number;
        for (let index = 0; index < monsterList.length; index++) {
            monster = monsterList[index];
            if(monster.config.startPos==0){
                endNode=this.leftEndNode;
            }else if(monster.config.startPos==1){
                endNode=this.middleEndNode;
            }else{
                endNode=this.rightEndNode;
            }
            dis=Vec3.distance(monster.node.worldPosition,endNode.worldPosition);
            if(dis<=this.weapon.weaponConfig.attackDistance){
                if(dis<minDis){
                    minDis=dis;
                }
            }
        }
        return minDis;
    }

    /**
     * 武器攻击
     */
    WeaponAttack():void{
        //只要开了第一枪就不算新玩家了
        GameModel.single.isNewPlayer=false;

        
        let monsterList:MonsterBase[];
        let monsterLists:Array<Array<MonsterBase>>=[];
        //攻击1条路
        if(this.weapon.weaponConfig.attackRange==1){
            if(this.weapon.fireKey==1){
                monsterList=this.leftMonsterList;
            }else if(this.weapon.fireKey==2){
                monsterList=this.middleMonsterList;
            }else{
                monsterList=this.rightMonsterList;
            }
            if(monsterList.length==0){
                return;
            }
            monsterList.sort(this.monsterSortFunc);
            monsterLists.push(monsterList);
        }else if(this.weapon.weaponConfig.attackRange==2){//攻击2条路
            //左
            if(this.weapon.fireKey==1){
                if(this.leftMonsterList.length>0){
                    this.leftMonsterList.sort(this.monsterSortFunc);
                    monsterLists.push(this.leftMonsterList);
                }
                if(this.middleMonsterList.length>0){
                    this.middleMonsterList.sort(this.monsterSortFunc);
                    monsterLists.push(this.middleMonsterList);
                }
            }else if(this.weapon.fireKey==2){//中
                if(this.middleMonsterList.length>0){
                    this.middleMonsterList.sort(this.monsterSortFunc);
                    monsterLists.push(this.middleMonsterList);
                }
                //随机左边/右边
                let random:number=Math.random();
                if(random>0.5){
                    if(this.rightMonsterList.length>0){
                        this.rightMonsterList.sort(this.monsterSortFunc);
                        monsterLists.push(this.rightMonsterList);
                    }
                }else{
                    if(this.leftMonsterList.length>0){
                        this.leftMonsterList.sort(this.monsterSortFunc);
                        monsterLists.push(this.leftMonsterList);
                    }
                }
            }else{//右
                if(this.rightMonsterList.length>0){
                    this.rightMonsterList.sort(this.monsterSortFunc);
                    monsterLists.push(this.rightMonsterList);
                }
                if(this.middleMonsterList.length>0){
                    this.middleMonsterList.sort(this.monsterSortFunc);
                    monsterLists.push(this.middleMonsterList);
                }
            }
        }else{//攻击3条路
            if(this.leftMonsterList.length>0){
                this.leftMonsterList.sort(this.monsterSortFunc);
                monsterLists.push(this.leftMonsterList);
            }
            if(this.middleMonsterList.length>0){
                this.middleMonsterList.sort(this.monsterSortFunc);
                monsterLists.push(this.middleMonsterList);
            }
            if(this.middleMonsterList.length>0){
                this.middleMonsterList.sort(this.monsterSortFunc);
                monsterLists.push(this.middleMonsterList);
            }
        }
        //没有任何怪物可以攻击
        if(monsterLists.length==0){
            return;
        }
        //攻击怪物
        let monster:MonsterBase;
        let endNode:Node;
        let index:number=0;
        let total:number=0;
        let dis:number=0;
        monsterLists.forEach(monsterList => {
            //攻击怪物
            index=0;
            total=Math.min(this.weapon.weaponConfig.attackCount,monsterList.length);
            while(index<total){
                monster=monsterList[index];
                if(monster.config.startPos==0){
                    endNode=this.leftEndNode;
                }else if(monster.config.startPos==1){
                    endNode=this.middleEndNode;
                }else{
                    endNode=this.rightEndNode;
                }
                if(Vec3.distance(monster.node.worldPosition,endNode.worldPosition)<=this.weapon.weaponConfig.attackDistance){
                    if(this.currentSkill!=null){
                        monster.Damage(this.weapon.weaponConfig.damage*this.currentSkill.damage);
                    }else{
                        monster.Damage(this.weapon.weaponConfig.damage);
                    }
                }else{
                    console.log("超出枪械攻击距离Miss");
                }
                index++;
                total=Math.min(this.weapon.weaponConfig.attackCount,monsterList.length);
            }
            for (let index = 0; index < monsterList.length; index++) {
                monster = monsterList[index];
                //怪物死亡
                if(monster.isDie){
                    //增加怒气
                    GameModel.single.angerCount+=monster.config.anger;
                    //增加击杀量
                    GameModel.single.killCount++;
                    //增加积分
                    if(monster.config.integral>0){
                        GameModel.single.integral+=monster.config.integral;
                    }
                    //从列表中删除
                    monsterList.splice(index,1);
                    index--;
                }
            }
        });
    }

    private monsterSortFunc(a:MonsterBase,b:MonsterBase):number{
        if(a.node.position.z>b.node.position.z){
            return -1;
        }else if(a.node.position.z<b.node.position.z){
            return 1;
        }
        return 0;
    }

    /**
     * 根据配置生成怪物
     * @param config 
     */
    private CreateMonster(config:any):Node{
        let monsterConfig:any=GameConfigManager.GetMonsterConfig(config.monsterId);
        if(monsterConfig==null){
            throw new Error("找不到怪物配置："+config.monsterId);
        }
        let prefab:Prefab=loader.getRes(monsterConfig.prefab);
        let monster:Node=instantiate(prefab);
        monster.name="Monster"+config.mId;
        let monsterScript=monster.addComponent(MonsterBase);
        monsterScript.config=config;
        //左
        if(config.startPos==0){
            monster.setPosition(this.leftStartNode.worldPosition);
            this.leftMonsterList.push(monsterScript);
        }else if(config.startPos==1){//中
            monster.setPosition(this.middleStartNode.worldPosition);
            this.middleMonsterList.push(monsterScript);
        }else{//右
            monster.setPosition(this.rightStartNode.worldPosition);
            this.rightMonsterList.push(monsterScript);
        }
        //创建血条
        monsterScript.hpView=MonsterHPUIPool.Create();
        monsterScript.hpView.monster=monsterScript;
        return monster;
    }

    private CreateWeapon(leftHand:AnimationComponent,rightHand:AnimationComponent):any{
        let config:any=GameConfigManager.GetWeaponConfig(GameModel.single.currentWeaponId);
        if(config.fireType==0){
            return new SingleShotWeapon(leftHand,rightHand);
        }else if(config.fireType==1){
            return new AutomaticFifleWeapon(leftHand,rightHand);
        }
        return new SingleShotWeapon(leftHand,rightHand);;
    }

    get scene(){
        return director.getScene();
    }

    private static instance:GameController;
    public static get single(){
        if(this.instance==null){
            this.instance=new GameController();
        }
        return this.instance;
    }
}
