import Sprite3D = Laya.Sprite3D;
import Vector3 = Laya.Vector3;
import { PlayerControl } from "./PlayerControl";
import { AccountManager } from "../Net/AccountManager";
import GamePool from "../Tools/GamePool";
import { AssetManager } from "../Tools/AssetManager";
import { GameTools, Transform3DHelper } from "../Tools/GameTools";
import { Runner } from "./Runner";
import { StageControl } from "./StageControl";
import { EventManager, StageState } from "../Tools/EventManager";
import { GameManager } from "./GameManager";
import InGameView from "../View/InGameView";
import { WXSDK } from "../Net/WXSDK";
import Dictionary from "../Tools/Dictionary";
export enum BossState{Idle,Run,Die,Walk};
export class Boss extends Laya.Script{
    private static ins:Boss;
    private raypos:Laya.Sprite3D;
    private arrowpos:Laya.Sprite3D;
    private archerpos:Laya.Sprite3D;
    private BossDistance:number;
    private _bossstate:BossState;
    private canmove:boolean = false;
    private FowardHit:Laya.HitResult = new Laya.HitResult();
    private isfence:boolean = false;
    constructor(){
        super();
        EventManager.StageOn(StageState.Press,this,this.AddSpeed)
        EventManager.StageOn(StageState.UnPress,this,this.SlowSpeed)
        EventManager.StageOn(StageState.Win,this,this.GameOver)
        EventManager.StageOn(StageState.Lose,this,this.GameOver)
    }
    public static get Instance():Boss{
        if(Boss.ins){
            return Boss.ins
        }
        else{
            return new Boss();
        }
    }
    //玩家
    public Player:Sprite3D;


    //箭
    private m_arrow:Laya.Sprite3D;
    //箭组
    public arrowarray:Laya.Sprite3D[] = [];
    //箭速
    private m_arrowspeed = 0;

    //boss
    private m_bossmodel:Sprite3D;
    //boss动画控制器
    private m_bossanimator:Laya.Animator;
    //boss马模型
    private m_horsemodel:Laya.Sprite3D;
    //boss马的动画控制器
    private m_horseanimator:Laya.Animator;

    private isdead:boolean;
    //boss攻击的时间间隔
    private AtkInterval:number = 0;
    //当前关卡数
    private level:number;
    //boss移动速度
    private BossSpeed:number = 1;
    //BOSS总血量
    private BossHp:number;
    //BOSS目前血量
    private NowBossHp:number;
    //血量条
    private BossProgress:Laya.ProgressBar;
    //创建地面
    private CreatGround:boolean = false;
    //随机方向
    private randomdir:boolean = false;

    private ArrowList:Dictionary<Sprite3D,any[]>=new Dictionary();

    onAwake(){
        this.m_bossmodel = this.owner as Laya.Sprite3D;
        this.m_horsemodel = this.m_bossmodel.parent as Laya.Sprite3D;
        this.m_bossanimator = this.m_bossmodel.getComponent(Laya.Animator) as Laya.Animator;
        this.m_horseanimator = this.m_horsemodel.getComponent(Laya.Animator) as Laya.Animator;
        this.arrowpos = this.m_bossmodel.getChildByName("arrowpos") as Laya.Sprite3D;
        this.archerpos = this.m_bossmodel.getChildByName("archerpos") as Laya.Sprite3D;
        this.raypos = this.m_bossmodel.getChildByName("raypos") as Laya.Sprite3D;
        this.CreatRay(this.raypos.transform.position.clone(),this.raypos.transform.rotationEuler.clone(),this.raypos);
        this.CreatArcher(this.archerpos.transform.position.clone(),this.archerpos.transform.rotationEuler.clone(),this.archerpos);
        this.Player = PlayerControl.Instance.Player;
        
        let stage = Number(AccountManager.Instance.curplayerData.GainAccount("stage"));
        this.BossHp = Number( StageControl.Instance.curstagedic[stage].BossHp);
        // this.BossHp = StageControl.Instance.curstage.BossHp;
        this.NowBossHp = this.BossHp;
        this.AddHpUI();
        this.BossDistance = AccountManager.Instance.curplayerData.BossDistance*1.65;
        this.level = AccountManager.Instance.curplayerData.GainAccount("stage");
        this.AtkInterval = AccountManager.Instance.curplayerData.BossAtkInterval - (this.level-1)*0.5;
        this.m_arrowspeed = AccountManager.Instance.curplayerData.ArrowSpeed;
    }
    onUpdate(){
        if(this.isdead)return
        var dis = Vector3.distance(this.Player.transform.position,this.m_bossmodel.transform.position);
        if(dis <= this.BossDistance && !this.run){
            this.run = true;
            WXSDK.Shake();
            this.ChangeState(BossState.Run);
        }
        if(dis>=AccountManager.Instance.curplayerData.MaxBossDistance*1.65 && this.run){
            // this.ChangeState(BossState.Walk)
            this.canmove = false;
        }
        else if(dis>AccountManager.Instance.curplayerData.MinBossDistance*1.65 && dis<AccountManager.Instance.curplayerData.MaxBossDistance*1.65 && this.run){
            this.ChangeState(BossState.Run)
            this.canmove = true;
            this.BossSpeed = StageControl.Instance.curstage.mainrolespeed;
        }
        // else if(dis<= AccountManager.Instance.curplayerData.MinBossDistance && this.run){
        //     this.ChangeState(BossState.Run)
        //     this.canmove = true;
        //     this.BossSpeed = StageControl.Instance.curstage.mainrolespeed;
        // }
        if(!this.canmove)return
        this.Move(this.BossMoveDir,this.BossSpeed);
        if(!this.atk){
            this.atk = true;
            Laya.timer.once(this.AtkInterval*1000,this,this.Atk);
        }
        if(!this.CreatGround && this.m_bossmodel.transform.position.z > StageControl.Instance.LastGround-50){
            StageControl.Instance.CreatGround(5);
        }
        if(!this.randomdir){
            this.randomdir = true;
            Laya.timer.once(2000,this,this.RandomDir);
        }
        this.RayCheck();

        if(this.ArrowList!=null)
        {
            var keys=this.ArrowList.keys;

            for(var i=0;i<keys.length;i++)
            {
                var key=keys[i];
                if(keys[i]!=null)
                {
                    var value=this.ArrowList.getValue(keys[i]);
                    this.ArrowMove(key,(this.ArrowList.getValue(key))[0],(this.ArrowList.getValue(key))[1]);
                }
            }
        }
    }

    currotV = new Vector3();
    currot = new Laya.Quaternion;
    NormalizeSpeed:Vector3 = new Vector3();
    curpos:Vector3 = new Vector3();
    offest:Vector3 = new Vector3();

    TurnDir(_dir:Vector3)
    {
        if(_dir.x != 0)
        {
            Vector3.lerp(this.currotV,_dir,0.35,_dir);
            this.currotV = _dir;
            Laya.Quaternion.rotationLookAt(_dir,new Vector3(0,1,0),this.currot);
            Laya.Quaternion.slerp(this.m_horsemodel.transform.rotation,this.currot,0.025,this.currot);
            this.currot = new Laya.Quaternion(0,this.currot.y,0);
            this.m_horsemodel.transform.rotation = this.currot;
        }
    }
    
    MoveX(_speed:number){
        //边界控制
        if(this.m_horsemodel.transform.position.x<0 && _speed<0 && this.isfence){
            return 
        }
        else if(this.m_horsemodel.transform.position.x>0 &&_speed>0 && this.isfence){
            return
        }
        else if(this.m_horsemodel.transform.position.x>=GameManager.Instance.fenceleftpos && _speed>0){
            return
        }
        else if(this.m_horsemodel.transform.position.x<=GameManager.Instance.fencerightpos && _speed<0){
            return
        }
        _speed *= 0.07;
        // this.RayDir = new Vector3(_speed,0,0);
        this.m_horsemodel.transform.translate(new Vector3(_speed,0,0));
    }
    offestx = 0;
    //随机方向
    RandomDir(){
        let _dir = Math.random()>0.5?-0.5:0.5;
        // let _dir = GameTools.RandomANumber(-30,30);
        // let offestX = new Vector3(-_dir*0.005,0,0);
        // this.offestx = GameTools.Instance.lerp(this.offestx,_dir,0.015);
        this.BossMoveDir = new Vector3(_dir,0,1);
        // this.MoveX(-this.offestx);
        // this.TurnDir(offestX);

        Laya.timer.once(200,this,()=>{
            // this.m_horsemodel.transform.rotationEuler = new Vector3(0,0,0);
            this.BossMoveDir = new Vector3(0,0,1);
            this.randomdir = false;
        })
    }
    atk = false;
    run = false;
    curspeed = 0;
    BossMoveDir = new Vector3(0,0,1);

    Move(_dir:Vector3,_speed:number){
        var sp = GameTools.Instance.lerp(this.curspeed,_speed,0.1);
        this.curspeed = sp;
        Vector3.scale(_dir,this.curspeed,this.offest);
        Vector3.add(this.m_horsemodel.transform.position,this.offest,this.curpos);
        Vector3.lerp(this.m_horsemodel.transform.position,this.curpos,0.15,this.curpos);
        this.m_horsemodel.transform.position = this.curpos;    
        this.m_horsemodel.transform.position = this.m_horsemodel.transform.position.x<GameManager.Instance.fencerightpos+0.5?new Vector3(GameManager.Instance.fencerightpos+0.5,this.m_horsemodel.transform.position.y,this.m_horsemodel.transform.position.z):this.m_horsemodel.transform.position;
        this.m_horsemodel.transform.position = this.m_horsemodel.transform.position.x>GameManager.Instance.fenceleftpos-0.5?new Vector3(GameManager.Instance.fenceleftpos-0.5,this.m_horsemodel.transform.position.y,this.m_horsemodel.transform.position.z):this.m_horsemodel.transform.position;
    }
    CurrectRotate = new Laya.Quaternion();
    Atk(){
        Laya.timer.frameLoop(1,this,this.RotationMove);
    }
    SlowSpeed(){
        if(this.run){
            this.ChangeState(BossState.Walk);
            this.BossSpeed = AccountManager.Instance.curplayerData.BossSpeed/2;
        }
    }
    AddSpeed(){
        if(this.run){
            this.ChangeState(BossState.Run);
            this.BossSpeed = AccountManager.Instance.curplayerData.BossSpeed;
        }
    }
    GameOver(){
        EventManager.StageOff(StageState.Press,this,this.AddSpeed);
        EventManager.StageOff(StageState.UnPress,this,this.SlowSpeed);
    }

    RotationMove(){
        Vector3.subtract(this.Player.transform.position,this.m_bossmodel.transform.position,this.currotV);
        Vector3.normalize(this.currotV,this.currotV);
        var curdir = new Vector3(-this.currotV.x,-this.currotV.y,-this.currotV.z);
        Laya.Quaternion.rotationLookAt(curdir,new Vector3(0,10,0),this.CurrectRotate);
        this.CurrectRotate.invert(this.CurrectRotate);
        Laya.Quaternion.slerp(this.m_bossmodel.transform.rotation,this.CurrectRotate,0.05,this.CurrectRotate);
        this.m_bossmodel.transform.rotation = this.CurrectRotate;
        var bossfoward = Transform3DHelper.getForward(this.m_bossmodel.transform);

        let _angle = this.JupdeAngle(bossfoward,this.currotV);
        if(_angle>0.995){
            Laya.timer.clear(this,this.RotationMove);
            this.Shoot();
            let rotation2 = GameTools.tweenRotate(this.m_bossmodel.transform, new Vector3(0, 0, 0), 700, Laya.Ease.linearInOut, Laya.Handler.create(this, () => {
                rotation2.clear();
                this.atk = false;
            }))
        }
    }
    /**判断boss旋转角度 --如果返回值为-1，则为平行*/
    private  JupdeAngle(dir1:Vector3,dir2:Vector3):number
    {
        let Dir1 = new Vector3(dir1.x,0,dir1.z);
        let Dir2 = new Vector3(dir2.x,0,dir2.z);
        Vector3.normalize(Dir1,Dir1);
        Vector3.normalize(Dir2,Dir2);
        var dot = Vector3.dot(Dir1, Dir2);     //d2.normalized向量归一化
        return dot;
    }
    /**boss射击 */
    Shoot(){
        this.CreatArrow();
        var currect=this.m_arrow;
        this.m_arrow=null;
        let ray = this.owner.getChildByName("raypos").getChildAt(0) as Laya.Sprite3D;
        let forw = Transform3DHelper.getForward(ray.transform);
        let raypos = this.owner.getChildByName("raypos") as Laya.Sprite3D;
        let trans = raypos.transform;
        let testRay = new Laya.Ray(new Vector3(trans.position.x,trans.position.y-1,trans.position.z),forw);
        let hitRes = new Laya.HitResult();
        this.m_bossanimator.play("shoot");
        if(AssetManager.Instance.mainscene.physicsSimulation.rayCast(testRay,hitRes)){
            let target = hitRes.collider.owner.parent as Laya.Sprite3D;
            // Laya.timer.frameLoop(1,this,this.ArrowMove,[this.m_arrow,forw,target]);
            this.ArrowList.add(currect,[forw,target]);
            
        }
        else{
            // Laya.timer.frameLoop(1,this,this.ArrowMove,[this.m_arrow,forw])
            this.ArrowList.add(currect,[forw,null]);
        }
    }
    recover = false;
    speed = 0;
    arrowoffset = new Vector3();
    arrowcurpos = new Vector3();
     //箭的移动
     ArrowMove(arrow:Laya.Sprite3D,_dir:Vector3,target?){
        if (target) {
            if (arrow.destroyed) return;
            if (arrow.transform.position.z <= target.transform.position.z) {
                if(target.name == "player"){
                    let _runner = target.getComponent(Runner) as Runner;
                    _runner.isdead = true;
                    this.BossProgress.visible = false;
                }
                if(this.ArrowList.containKey(arrow))
                    {
                        this.ArrowList.remove(arrow);
                    }
                GamePool.Instance.RecoveryModel(arrow);

            }
            else {
                var sp = GameTools.Instance.lerp(this.speed, this.m_arrowspeed, 0.1);
                this.speed = sp;
                Vector3.scale(_dir, this.speed, this.arrowoffset);
                Vector3.add(arrow.transform.position, this.arrowoffset, this.arrowcurpos);
                Vector3.lerp(arrow.transform.position, this.arrowcurpos, 0.15, this.arrowcurpos);
                arrow.transform.position = this.arrowcurpos;
            }
        }
        else {
            var sp = GameTools.Instance.lerp(this.speed, this.m_arrowspeed, 0.1);
            this.speed = sp;
            Vector3.scale(_dir, this.speed, this.arrowoffset);
            Vector3.add(arrow.transform.position, this.arrowoffset, this.arrowcurpos);
            Vector3.lerp(arrow.transform.position, this.arrowcurpos, 0.15, this.arrowcurpos);
            arrow.transform.position = this.arrowcurpos;
            if(!this.recover){
                this.recover = true;
                Laya.timer.once(1000, this, () => {
                    if(this.ArrowList.containKey(arrow))
                    {
                        this.ArrowList.remove(arrow);
                    }
                    GamePool.Instance.RecoveryModel(arrow);
                    this.recover = false;
                })
            }
        }
    }

    ChangeState(_state:BossState){
        if(this._bossstate == _state)return
        this._bossstate = _state;
        switch (this._bossstate) {
            case BossState.Idle:
                this.Idle();
                break;
            case BossState.Run:
                this.Run();
                break;
            case BossState.Die:
                this.Die();
                break
            case BossState.Walk:
                this.Walk();
                break;
        }
    }
    Idle(){
        this.m_bossanimator.play("idle");
        this.m_horseanimator.play("idle");
    }
    Walk(){
        this.m_horseanimator.play("walk");
        this.m_bossanimator.play("down");
    }
    Run(){
        this.canmove = true;
        this.m_bossanimator.play("down");
        this.m_horseanimator.play("run");
    }
    Die(){
        this.BossProgress.visible = false;
        this.isdead = true;
        Laya.timer.clearAll(this);
        this.m_horseanimator.play("idle");
        this.m_bossanimator.play("die");

        EventManager.StageTrigger(StageState.Win);
    }
    RayCheck(){
        if(this.FowardRayCheck){
            this.CrashBarrier();
        }
        else{
            this.isfence = false;
        }
    }
    CrashBarrier(){
        var target = this.FowardHit.collider.owner.parent as Laya.Sprite3D;
        if(target.name == "small_fence"){
            this.isfence = true;
        }
    }
    /**水平方向射线检测*/
    get FowardRayCheck():boolean{
        // this.FowardHit=null;
        var isFowardHit = false;
        var startPos:Vector3 = new Vector3(this.m_bossmodel.transform.position.x,this.m_bossmodel.transform.position.y+0.5,this.m_bossmodel.transform.position.z+2);
        let dir = Transform3DHelper.getForward(this.m_bossmodel.transform);
        var DownRay:Laya.Ray = new Laya.Ray(startPos,dir);
        if(AssetManager.Instance.mainscene.physicsSimulation.rayCast(DownRay,this.FowardHit,1)){
            if (this.FowardHit.collider.collisionGroup == 100 ) {
                // this.curlookspr = this.FowardHit.collider;
                isFowardHit = true;
            }
        }
        return isFowardHit;
    }


    //创建瞄准线
    CreatRay(pos:Laya.Vector3,euler:Laya.Vector3,raypos:Laya.Sprite3D){
        var ray = this.CreatRayPrefab();
        raypos.addChild(ray);
        ray.transform.position = pos;
        ray.transform.rotationEuler = euler;
        // let scale = ray.transform.scale.clone();
        // scale.z = 0.1;
        // scale.y = 3;
        // scale.x = 2;
        // ray.transform.scale = scale;
    }
    //创建瞄准线预设
    CreatRayPrefab():Laya.Sprite3D{
        var ray = GamePool.Instance.GetModel(AssetManager.Instance.Prop.get(18),"");
        return ray
    }
    //创建弓箭预设
    CreatArcher(_pos:Laya.Vector3,_euler:Laya.Vector3,archerpos:Laya.Sprite3D){
        var archer = GamePool.Instance.GetModel(AssetManager.Instance.Prop.get(16),"");
        archerpos.addChild(archer);
        archer.transform.position = _pos;
        archer.transform.rotationEuler = _euler;
        var scale = archer.transform.scale.clone();
        scale.x = 0.3;
        scale.y = 0.3;
        scale.z = 0.6;
        archer.transform.scale = scale;
    }
    //创建箭的预设
    CreatArrow(){
        var arrow = GamePool.Instance.GetModel(AssetManager.Instance.Prop.get(17),"");
        AssetManager.Instance.mainscene.addChild(arrow);
        this.arrowarray.push(arrow);
        arrow.transform.position = this.arrowpos.transform.position.clone();
        var euler = this.arrowpos.transform.rotationEuler.clone();
        arrow.transform.rotationEuler = euler;
        let scale = arrow.transform.scale.clone();
        scale.z = 0.5;
        scale.x = 0.5;
        scale.y = 0.5;
        arrow.transform.scale = scale;
        this.m_arrow = arrow;
    }
    AddHpUI(){
        this.BossProgress = new Laya.ProgressBar();
        this.BossProgress.skin = "Game/res/textrue/healthbar1.png";
        this.BossProgress.scaleX = 0.4;
        this.BossProgress.scaleY = 0.4;
        this.BossProgress.anchorX = 0.5;
        this.BossProgress.anchorY = 0.5;
        Laya.stage.addChild(this.BossProgress);
        GameManager.Instance.UIArray.push(this.BossProgress);
        let UIPos = this.m_bossmodel.getChildByName("UIPos") as Laya.Sprite3D;
        this.InitHpUI();
        
        Laya.timer.frameLoop(1,this,()=>{
            let ScreenPos = new Vector3();
            AssetManager.Instance.maincamera.worldToViewportPoint(UIPos.transform.position,ScreenPos);
            this.BossProgress.pos(ScreenPos.x,ScreenPos.y);
        })
    }
    InitHpUI(){
        this.BossProgress.value = this.NowBossHp/this.BossHp;
    }

    /** BOSS掉血方法 */
    LoseHp(_damage:number){
        GameManager.Instance.KillNum++;
        InGameView.Instance.InitUI();
        if(this.NowBossHp >= _damage){
            this.NowBossHp = this.NowBossHp -= _damage;
        }
        else if(this.NowBossHp < _damage && this.NowBossHp>0){
            this.NowBossHp = 0;
        }
        if(this.NowBossHp == 0){
            this.ChangeState(BossState.Die);
            this.BossProgress.destroy();
        }
        else{
            this.InitHpUI();
        }
    }

}