import Vector3 = Laya.Vector3;
import Sprite3D = Laya.Sprite3D;
import { GameTools, Transform3DHelper } from "../Tools/GameTools";
import { EventManager, EventState, StageState } from "../Tools/EventManager";
import { AssetManager } from "../Tools/AssetManager";
import GamePool from "../Tools/GamePool";
import { GameManager } from "./GameManager";
import { NpcRunner } from "./NpcRunner";
import { ChaseNpc } from "./ChaseNpc";
import { StageControl } from "./StageControl";
import { AccountManager } from "../Net/AccountManager";
import { Hostage } from "./Hostage";
import { Boss } from "./Boss";
import InGameView from "../View/InGameView";
import { AudioManager, MusicType } from "../Tools/AudioManager";
import ResDic from "../Tools/ResDic";
import Dictionary from "../Tools/Dictionary";
import { WXSDK } from "../Net/WXSDK";
import MainGameView from "../View/MainGameView";
//人物状态
export enum CharacterState{Run,Idle,Die,Win,Shoot,Walk,Revive}
export class Runner extends Laya.Script3D{
    private static ins:Runner;
    //无敌状态
    public Invincible:boolean = false;
    public started:boolean = false;
    //当前关卡
    private stage:number;
    //玩家攻击力
    m_PlayerDamage:number;
    //玩家
    m_player:Sprite3D;
    //玩家的动画控制器
    m_animator:Laya.Animator;
    //马的动画控制器
    m_horseanimator:Laya.Animator;
    //人物状态
    m_characterstate:CharacterState;
    //箭
    m_arrow:Laya.Sprite3D;
    //箭的位置
    m_arrowpos:Laya.Sprite3D;
    //射线的位置
    m_raypos:Laya.Sprite3D;
    //弓的位置
    m_archerpos:Laya.Sprite3D;  
    //射程
    m_range:number;

    shoot:boolean = false;
    //是否打到障碍
    isbarrier:boolean = false;
    //是否打到栅栏
    isfence:boolean = false;
    //箭组
    public arrowarray:Sprite3D[] = [];
    public isdead:boolean = false;
    public canmove:boolean = false;
    //人物速度
    private _speed:number = 0;
    //是否处于按压状态
    public _press:boolean = false;
    //射线方向
    public RayDir:Vector3 = new Vector3();
    //下方射线打到的物体
    private DownHit:Laya.HitResult = new Laya.HitResult();
    //前方射线打到的物体
    private FowardHit:Laya.HitResult = new Laya.HitResult();

    constructor(){
        super();
        EventManager.StageOn(StageState.Start,this,this.Begin);
        EventManager.StageOn(StageState.Lose,this,this.GameOver);
        EventManager.StageOn(StageState.Win,this,this.GameOver);
    }
    public static get Instance():Runner{
        if(Runner.ins){
            return Runner.ins
        }
        else{
            return new Runner();
        }
    }
    onAwake(){
        this.m_player = this.owner as Sprite3D;
        this.m_animator = this.owner.getComponent(Laya.Animator) as Laya.Animator;
        this.m_arrowpos = this.owner.getChildByName("arrowpos") as Laya.Sprite3D;
        this.m_raypos = this.owner.getChildByName("raypos") as Laya.Sprite3D;
        this.m_archerpos = this.owner.getChildByName("archerpos") as Laya.Sprite3D;
        this.m_horseanimator = this.owner.getChildAt(this.owner.numChildren-1).getComponent(Laya.Animator) as Laya.Animator;
        this._speed = StageControl.Instance.curstage.mainrolespeed;
        // this._speed = 1.5;
        this.m_PlayerDamage = AccountManager.Instance.curplayerData.PlayerDamage;
        this.stage =Number(AccountManager.Instance.curplayerData.GainAccount("stage"));
        this.ChangeState(CharacterState.Idle);
      
        this.DirRoatationLerp = AccountManager.Instance.curplayerData.DirRoatationLerp;
        this.DirMoveLerp = AccountManager.Instance.curplayerData.DirMoveLerp;
        this.arrowspeed = AccountManager.Instance.curplayerData.ArrowSpeed;
        this.m_range = AccountManager.Instance.curplayerData.Range;
    }
    Begin(){
        this.canmove = true;
        this.CreatArrow();
        this.ChangeState(CharacterState.Walk);
    }
    curspeed = 0;
    onUpdate(){
        if(this.isdead){
            this.ChangeState(CharacterState.Die);
            return;
        }
        if(this.canmove && this.started){
            var speed;
            if(!this.isbarrier){
                // if(this.stage>1){
                    if(this._press){
                        speed = StageControl.Instance.curstage.mainrolespeed;
                        // speed = 1.5;
                    }
                    else{
                        speed = StageControl.Instance.curstage.mainrolespeed/2;
                        // speed = 0.8;
                    }
                    let foward = Transform3DHelper.getForward(this.m_player.transform);
                    this.Move(foward,speed);
                // }
                // else{
                //     let foward = Transform3DHelper.getForward(this.m_player.transform);
                //     speed = StageControl.Instance.curstage.mainrolespeed/2;
                //     this.Move(foward,speed);
                // }
            }
        }
        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]);
                }
            }
        }

    }
    MoveX(_speed:number){
        //边界控制
        if(this.m_player.transform.position.x<0 && _speed<0 && this.isfence){
            return 
        }
        else if(this.m_player.transform.position.x>0 &&_speed>0 && this.isfence){
            return
        }
        else if(this.m_player.transform.position.x>=GameManager.Instance.fenceleftpos && _speed>0){
            return
        }
        else if(this.m_player.transform.position.x<=GameManager.Instance.fencerightpos && _speed<0){
            return
        }
        _speed *= this.DirMoveLerp;
        if(this.canmove && this.started){
            this.m_player.transform.translate(new Vector3(_speed,0,0));
        }
        // this.m_player.transform.position = this.m_player.transform.position.x < -4.5?new Vector3(-4.5,this.m_player.transform.position.y,this.m_player.transform.position.z):this.m_player.transform.position;
        // this.m_player.transform.position = this.m_player.transform.position.x > 4.5?new Vector3(4.5,this.m_player.transform.position.y,this.m_player.transform.position.z):this.m_player.transform.position;
    }
    currotV = new Vector3();
    currot = new Laya.Quaternion;
    NormalizeSpeed:Vector3 = new Vector3();
    curpos:Vector3 = new Vector3();
    offest:Vector3 = new Vector3();


    DirRoatationLerp:number;
    DirMoveLerp:number;
    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_player.transform.rotation,this.currot,this.DirRoatationLerp,this.currot);
            this.currot = new Laya.Quaternion(0,this.currot.y,0);
            this.m_player.transform.rotation = this.currot;
        }
    }
    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_player.transform.position,this.offest,this.curpos);
        Vector3.lerp(this.m_player.transform.position,this.curpos,0.15,this.curpos);
        
        this.curpos = new Vector3(this.curpos.x,this.curpos.y,this.curpos.z);
        
        this.m_player.transform.position = this.curpos;
        this.m_player.transform.position = this.m_player.transform.position.x<GameManager.Instance.fencerightpos+0.5?new Vector3(GameManager.Instance.fencerightpos+0.5,this.m_player.transform.position.y,this.m_player.transform.position.z):this.m_player.transform.position;
        this.m_player.transform.position = this.m_player.transform.position.x>GameManager.Instance.fenceleftpos-0.5?new Vector3(GameManager.Instance.fenceleftpos-0.5,this.m_player.transform.position.y,this.m_player.transform.position.z):this.m_player.transform.position;
    }
    ChangeState(_state:CharacterState){
        if(this.m_characterstate == _state)return
        this.m_characterstate = _state;
        switch (this.m_characterstate) {
            case CharacterState.Idle:
                this.Idle();
                break;
            case CharacterState.Run:
                this.Run();
                break
            case CharacterState.Die:
                this.Die();
                break;
            case CharacterState.Shoot:
                this.Shoot();
                break;
            case CharacterState.Walk:
                this.Walk();
                break;
        }
    }
    Idle(){
        this.m_animator.play("idle");
        this.m_horseanimator.play("idle");
    }
    Run(){
        this.m_animator.play("down");
        // this.m_animator.play("idle");
        this.m_horseanimator.play("run");
    }
    ReviveState(){
        this.m_horseanimator.play("walk");
        this.m_animator.play("down");
    }
    Die(){
        WXSDK.Shake(true);
        this.canmove = false;
        this.m_animator.play("die");
        this.m_horseanimator.play("idle");
        // this.m_raypos.removeSelf();
        // this.m_raypos.destroy();
        // this.m_arrowpos.destroy();
        // this.m_archerpos.destroy();
        // this.m_arrow.destroy();
        EventManager.StageTrigger(StageState.Lose);
    }
    GameOver(){
        Laya.timer.clear(this,this.AnimatorState);
        EventManager.StageOff(StageState.Start,this,this.Begin);
        // Laya.timer.clearAll(this);
    }
    Walk(){
        this.m_horseanimator.play("walk");
        // this.m_animator.play("down")
    }
    Shoot(){
        this.m_animator.play("shoot");
        // this.m_animator.play("run");
    }
    RayCheck(){
        if(this.FowardRayCheck){
            this.CrashBarrier();
        }
        else{
            this.isbarrier = false;
            this.isfence = false;
        }
    }
    //撞到障碍物
    CrashBarrier(){
        var target = this.FowardHit.collider.owner.parent as Laya.Sprite3D;
        if(target.name == "stone"){
            this.isbarrier = true;
        }
        else if(target.name == "bonfire"){
            this.ChangeState(CharacterState.Die);
        }
        else if(target.name == "big_fence"){
            this.isbarrier = true;
        }
        else if(target.name == "wood_Cylinder"){
            this.isbarrier = true
        }
        else if(target.name == "small_fence"){
            this.isfence = true;
        }
    }
    curlookspr:Laya.PhysicsComponent;
    /**水平方向射线检测*/
    get FowardRayCheck():boolean{
        // this.FowardHit=null;
        var isFowardHit = false;
        var startPos:Vector3 = new Vector3(this.m_player.transform.position.x,this.m_player.transform.position.y+0.5,this.m_player.transform.position.z);
        let dir = Transform3DHelper.getForward(this.m_player.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;
    }
    private ArrowList:Dictionary<Sprite3D,any[]>=new Dictionary();
    //射箭
    Archery(){
        var currect=this.m_arrow;
        this.m_arrow=null;
        AudioManager.playMusic(MusicType.shoot);
        Laya.timer.clear(this,this.ArrowFollow);
        Laya.timer.clear(this,this.AnimatorState);
        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-0.5,trans.position.z),forw);
        let hitRes = new Laya.HitResult();
        this.m_animator.play("shoot");
        Laya.timer.frameLoop(1,this,this.AnimatorState);
        if(this.stage <= 2){
            if(AssetManager.Instance.mainscene.physicsSimulation.rayCast(testRay,hitRes,this.m_range)){
                let target = hitRes.collider.owner as Laya.Sprite3D;
                this.ArrowList.add(currect,[forw,target]);
            }
            else{
                this.ArrowList.add(currect,[forw,null]);
            }
        }
        else{
            if(AssetManager.Instance.mainscene.physicsSimulation.rayCast(testRay,hitRes)){
                let target = hitRes.collider.owner as Laya.Sprite3D;
                this.ArrowList.add(currect,[forw,target]);
            }
            else{
                this.ArrowList.add(currect,[forw,null]);
            }
        }
    }
    arrowspeed = 0 ;
    speed = 0;
    arrowoffset = new Vector3();
    arrowcurpos = new Vector3();
    recover = false;
    hitfence:boolean = false;
    //箭的移动
    ArrowMove(arrow:Laya.Sprite3D,_dir:Vector3,target?){
        if (target) {
            if (arrow.destroyed) return;
            let parent = target.parent as Laya.Sprite3D;
            if (arrow.transform.position.z >= parent.transform.position.z) {
                if (parent.name == "npc") {
                    // GameManager.Instance.KillNum++;
                    AudioManager.playMusic(MusicType.hit);
                    //新手指引关特殊处理
                    if(this.stage == 1){
                        if(InGameView.Instance.Guide2.visible){
                            if(GameManager.Instance.GuideKill <2){
                                GameManager.Instance.GuideKill += 1;
                            }
                            if(GameManager.Instance.GuideKill == 1){
                                this.started = true;
                                InGameView.Instance.Guide2.visible = false;
                                Laya.timer.once(2500,this,()=>{
                                    this.started = false;
                                    InGameView.Instance.Guide3.visible = true;
                                    this.m_range = 100;
                                })
                            }
                        }
                        // if(GameManager.Instance.GuideKill == 2){
                        //     // this.started = true;
                        //     this.m_range = 100;
                        //     if(InGameView.Instance.Guide2.visible){
                        //         WXSDK.AldEvent("完成第二阶段引导");
                        //         InGameView.Instance.Guide2.visible = false;
                        //         this.started = true;
                        //         Laya.timer.once(2000,this,()=>{
                        //             InGameView.Instance.Guide3.visible = true;
                        //             GameManager.Instance.three = true;
                        //             this.started = false;
                        //         })
                        //     }
                        // }
                    }
                    else if(this.stage == 2){
                        if(InGameView.Instance.Guide2.visible){
                            GameManager.Instance.GuideKill += 1;
                            if(GameManager.Instance.GuideKill >= 1){
                                this.started = true;
                                InGameView.Instance.Guide2.visible = false;
                                Laya.timer.once(2000,this,()=>{
                                    this.started = false;
                                    InGameView.Instance.Guide4.visible = true;
                                    this.m_range = 100;
                                })
                            }
                        }
                    }
                    let _npcrunner = parent.getComponent(NpcRunner) as NpcRunner;
                    let _chaseNpc = parent.getComponent(ChaseNpc) as ChaseNpc;
                    if (_npcrunner) {
                        let stage =Number(AccountManager.Instance.curplayerData.GainAccount("stage"));
                        if(stage == 1 ){
                            if(GameManager.Instance.GuideKill == 1){
                                if (target.name == "npcfrontcollider") {
                                    _npcrunner.frontdie = true;
                                }
                                else if (target.name == "npcrearcollider") {
                                    _npcrunner.reardie = true;
                                }
                                GameManager.Instance.KillNum ++ ;
                                InGameView.Instance.InitUI();
                            }
                        }
                        //指引提示出现之前 保证敌人不被击中
                        else if(stage == 2){
                            if(InGameView.Instance.Guide2.visible || GameManager.Instance.GuideKill==1){
                                if (target.name == "npcfrontcollider") {
                                    _npcrunner.frontdie = true;
                                }
                                else if (target.name == "npcrearcollider") {
                                    _npcrunner.reardie = true;
                                }
                            }
                            GameManager.Instance.KillNum ++ ;
                            InGameView.Instance.InitUI();
                        }
                        else if(stage >2){
                            if (target.name == "npcfrontcollider") {
                                _npcrunner.frontdie = true;
                            }
                            else if (target.name == "npcrearcollider") {
                                _npcrunner.reardie = true;
                            }
                            GameManager.Instance.KillNum ++ ;
                            InGameView.Instance.InitUI();
                        }
                        WXSDK.Shake(true);
                        WXSDK.stageShake();
                    }
                    else if (_chaseNpc) {
                        if(this.stage == 2){
                            if(InGameView.Instance.Guide4.visible && GameManager.Instance.GuideKill >= 1){
                                InGameView.Instance.Guide4.visible = false;
                                WXSDK.AldEvent("完成第四阶段引导");
                                this.started = true;
                                Laya.timer.once(3000,this,()=>{
                                    EventManager.StageTrigger(StageState.Win);
                                })
                                if (target.name == "npcfrontcollider") {
                                    _chaseNpc.frontdie = true;
                                }
                                else if (target.name == "npcrearcollider") {
                                    _chaseNpc.reardie = true;
                                }
                                GameManager.Instance.KillNum ++ ;
                                InGameView.Instance.InitUI();
                            }
                        }
                        else{
                            if (target.name == "npcfrontcollider") {
                                _chaseNpc.frontdie = true;
                            }
                            else if (target.name == "npcrearcollider") {
                                _chaseNpc.reardie = true;
                            }
                            GameManager.Instance.KillNum ++ ;
                            InGameView.Instance.InitUI();
                        }
                        WXSDK.Shake(true);
                        WXSDK.stageShake();
                    }
                }
                else if (parent.name == "big_fence") {
                    AudioManager.playMusic(MusicType.hit);
                    WXSDK.Shake(true);
                    if(this.stage == 1){
                        if ( GameManager.Instance.GuideKill >= 1) {
                            InGameView.Instance.Guide3.visible = false;
                            // this.m_range = 100;
                            if(!this.hitfence){
                                Laya.timer.once(5000,this,()=>{
                                    EventManager.StageTrigger(StageState.Win);
                                })
                                WXSDK.AldEvent("完成第三阶段引导");
                                this.started = true;
                                this.hitfence = true;
                            }
                            let tweenpos = GameTools.tweenMove(parent.transform, new Vector3(parent.transform.position.x, parent.transform.position.y, parent.transform.position.z + 5), 200, Laya.Ease.linearInOut, Laya.Handler.create(this, () => {
                                tweenpos.clear();
                            }));
                            let tweenrot = GameTools.tweenRotate(parent.transform, new Vector3(90, 0, 0), 500, Laya.Ease.linearInOut, Laya.Handler.create(this, () => {
                                tweenrot.clear();
                            }))
                            Laya.timer.once(500, this, () => {
                                GamePool.Instance.RecoveryModel(parent);
                            })
                        }
                    }
                    else{
                        let tweenpos = GameTools.tweenMove(parent.transform, new Vector3(parent.transform.position.x, parent.transform.position.y, parent.transform.position.z + 5), 200, Laya.Ease.linearInOut, Laya.Handler.create(this, () => {
                            tweenpos.clear();
                        }));
                        let tweenrot = GameTools.tweenRotate(parent.transform, new Vector3(90, 0, 0), 500, Laya.Ease.linearInOut, Laya.Handler.create(this, () => {
                            tweenrot.clear();
                        }))
                        Laya.timer.once(1000, this, () => {
                            GamePool.Instance.RecoveryModel(parent);
                        })
                    }
                }
                else if (parent.name == "hostage") {
                    if(this.stage > 1){
                        AudioManager.playMusic(MusicType.hit);
                        let _host = parent.getComponent(Hostage) as Hostage;
                        _host.isdead = true;
                    }
                }
                else if(parent.name == "boss"){
                    AudioManager.playMusic(MusicType.hit);
                    // GameManager.Instance.KillNum++;
                    let _boss = parent.getComponent(Boss) as Boss;
                    _boss.LoseHp(this.m_PlayerDamage);
                }
                // arrow.active = false;
                // Laya.timer.clear(this, this.ArrowMove);
                if(this.ArrowList.containKey(arrow))
                {
                    this.ArrowList.remove(arrow);
                }
                GamePool.Instance.RecoveryModel(arrow);
            }
            else {
                var sp = GameTools.Instance.lerp(this.speed, this.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.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(500, this, () => {
                    // Laya.timer.clear(this, this.ArrowMove);
                    if(this.ArrowList.containKey(arrow))
                    {
                        this.ArrowList.remove(arrow);
                    }
                    GamePool.Instance.RecoveryModel(arrow);
                    this.recover = false;
                })
            }
        }
    }

    
    //动画播放状态
    AnimatorState(){
        if(this.m_animator.getCurrentAnimatorPlayState(0).normalizedTime>=1){
            Laya.timer.clear(this,this.AnimatorState);
            if(!this.m_arrowpos.destroyed){
                this.CreatArrow();
                this.shoot = false;
                // this.m_animator.play("idle");
            }
        }
    }
    //创建箭的预设
    CreatArrow(){
        var arrow = GamePool.Instance.GetModel(AssetManager.Instance.Prop.get(17),"");
        AssetManager.Instance.mainscene.addChild(arrow);
        this.arrowarray.push(arrow);
        arrow.transform.position = this.m_arrowpos.transform.position.clone();
        var euler = this.m_arrowpos.transform.rotationEuler.clone();
        arrow.transform.rotationEuler = euler;
        let scale = arrow.transform.scale.clone();
        scale.z = 0.5;
        scale.x = 0.8;
        scale.y = 0.5;
        arrow.transform.scale = scale;
        this.m_arrow = arrow;
        Laya.timer.frameLoop(1,this,this.ArrowFollow,[arrow,this.m_arrowpos]);
    }
    //箭跟随玩家移动
    ArrowFollow(arrow,arrowpos){
        if(!arrowpos.destroyed){
            arrow.transform.position = arrowpos.transform.position.clone();
            arrow.transform.rotationEuler = arrowpos.transform.rotationEuler.clone();
        }
        else{
            Laya.timer.clear(this,this.ArrowFollow);
        }
    }
    Revive(){
        this.Invincible = true;
        Laya.timer.once(AccountManager.Instance.curplayerData.Invincible,this,()=>{
            this.Invincible = false;
        })
        this.ReviveState();
        this.m_player.transform.position = new Vector3(this.m_player.transform.position.x,this.m_player.transform.position.y,this.m_player.transform.position.z-15);
        this.canmove = true;
        this.ChangeState(CharacterState.Walk);
    }

}