

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using UnityEngine;
using Random = UnityEngine.Random;


/// <summary>
/// 动作状态
/// </summary>
public abstract class ActionFSMState : FSMState
{
    RoleEntity m_Role;
    public RoleEntity role => m_Role;

    public const string State_Name = "State";

    public string name => this.GetType().Name;
    
    protected ActionFSMState(FSMSystem fsm, RoleEntity role) : base(fsm)
    {
        m_Role = role;
    }


}

/// <summary>
/// 状态机控制器
/// </summary>
public class ActionFSMSystem : FSMSystem
{
    public ActionFSMSystem() : base()
    {
        
    }
    
    public static ActionFSMSystem InitPlayerActionFSM(PlayerEntity role)
    {
        ActionFSMSystem fsm = new ActionFSMSystem();

        ActionStateIdle idle = new ActionStateIdle(fsm,role);
        ActionStateRun run = new ActionStateRun(fsm,role);
        
        ActionStateDie lose = new ActionStateDie(fsm,role);
        ActionStateWin win = new ActionStateWin(fsm,role);
        
        Idle2RunTransition idle2Run = new Idle2RunTransition(idle,run);
        Run2IdleTransition run2Idle = new Run2IdleTransition(run,idle);
        MeetSignTransition any2Win = new MeetSignTransition(PlayerState.State_Win,win);
        Any2DieTransition normal2Lose = new Any2DieTransition(lose);
        
        idle.AddTransition(normal2Lose);
        idle.AddTransition(idle2Run);
        idle.AddTransition(any2Win);
        
        run.AddTransition(normal2Lose);
        run.AddTransition(run2Idle);
        run.AddTransition(any2Win);

        fsm.SetDefaultState(idle);
        
        return fsm;
    }
    
}

/// <summary>
/// 过程型动作
/// </summary>
public abstract class ProgressActionFSMState : ActionFSMState
{ 
    /// <summary>
    /// 开始时间
    /// </summary>
    protected float m_StartTime;
    /// <summary>
    /// 当前的进度时间
    /// </summary>
    public float curTime { get { return this.role.battleController.time - m_StartTime; } }

    /// <summary>
    /// 进度总时间
    /// </summary>
    protected float m_TotalTime;
    /// <summary>
    /// 进度总时间 get
    /// </summary>
    public float totalTime { get { return m_TotalTime; } }


    /// <summary>
    /// 当前进度 get
    /// </summary>
    public float progress
    {
        get
        {
            if (m_TotalTime == 0)
                return 1;

            return Mathf.Clamp01(this.curTime / m_TotalTime);
        }
    }

    /// <summary>
    /// 是否已完成 get
    /// </summary>
    public bool finished => this.curTime >= m_TotalTime;
    
    protected ProgressActionFSMState(FSMSystem fsm, RoleEntity role) : base(fsm, role)
    {
        
    }

    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();
        
        // 记录开始时间
        m_StartTime = this.role.battleController.time;
    }

    public override void Update()
    {
        base.Update();
        
    }

}

/// <summary>
/// 加了执行进度
/// </summary>
public abstract class DoubleProgressActionFSMState : ProgressActionFSMState
{
    /// <summary>
    /// 执行时间
    /// </summary>
    protected float m_ExecuteTime;

    /// <summary>
    /// 到m_ExecuteTime的进度
    /// </summary>
    public float executeProgress
    {
        get
        {
            if (m_ExecuteTime <= 0)
            {
                return 0;
            }

            float p = Mathf.Clamp01( this.curTime / m_ExecuteTime);
            return p;
        }
    }

    /// <summary>
    /// 是否已执行
    /// </summary>
    private bool m_WaitExecute = true;
    
    protected DoubleProgressActionFSMState(FSMSystem fsm, RoleEntity role) : base(fsm, role)
    {
        
    }

    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();   
        
        m_WaitExecute = true;

    }

    public override void Update()
    {
        base.Update();
        
        // 执行事件检测 在父类的Finish检测之前
        if (m_WaitExecute && this.curTime >= m_ExecuteTime)
        {
            this.OnExecute();
            m_WaitExecute = false;
        }
        
    }  
    
    /// <summary>
    /// 在达到执行时间时调用
    /// </summary>
    protected virtual void OnExecute()
    {
    }

}

/// <summary>
/// 正常
/// </summary>
public class ActionStateIdle : ActionFSMState
{
    public override int ID => PlayerState.idle;
    public ActionStateIdle(FSMSystem fsm, RoleEntity role) : base(fsm, role)
    {
        
    }


    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();


        if(this.role.rc)
            this.role.rc.roleMotion.SetAnimatorInteger(ActionFSMState.State_Name,(int)PlayerState.idle);
    }


    public override void Update()
    {
        base.Update();
       

    }

    public override void DoBeforeLeaving()
    {
        
    }
}

/// <summary>
/// 正常
/// </summary>
public class ActionStateRun : ActionFSMState
{
    public override int ID => PlayerState.run;
    public ActionStateRun(FSMSystem fsm, RoleEntity role) : base(fsm, role)
    {
        
    }


    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();
        

        if(this.role.rc)
            this.role.rc.roleMotion.SetAnimatorInteger(ActionFSMState.State_Name,(int)PlayerState.run);

        this.role.hasMoved = true;
    }

    public static float DirToRotateAngle(Vector2 dir)
    {
        if (Mathf.Abs(dir.x) <= 0.0000001f)
        {
            return dir.y > 0 ? 0 : 180;
        }
        
        float angle = -180 * (Mathf.Atan(dir.y / dir.x)) / Mathf.PI + 90;
        if (dir.x < 0)
        {
            angle += 180;
        }
        else if (dir.y < 0)
        {
            angle += 360;
        }
        angle %= 360;
        return angle;
    }
    
    public override void Update()
    {
        base.Update();
       
    }

    public override void DoBeforeLeaving()
    {
        
    }
}


public class ActionStateWin : ActionFSMState
{
    public override int ID => PlayerState.State_Win;
    

    public ActionStateWin(FSMSystem fsm, PlayerEntity role) : base(fsm, role)
    {
        
    }

    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();
        
        if(this.role.rc)
            this.role.rc.roleMotion.SetAnimatorInteger(ActionFSMState.State_Name,(int)PlayerState.State_Win);

        PlayerEntity player = this.role as PlayerEntity;
        if (player)
        {
            player.StopMove();

            player.transform.position = player.hoppingBattleController.HoppingBattle3DScene.winPos.position;//
                //Vector3.Lerp(role.transform.position,
                //player.hoppingBattleController.HoppingBattle3DScene.winPos.position, .5f);
            player.transform.localRotation = Quaternion.identity;
        }
    }
    
    public override void Update()
    {
        base.Update();
        
    }


    public override void DoBeforeLeaving()
    {
        base.DoBeforeLeaving();
        
    }
}

public class ActionStateLose : ActionFSMState
{
    public override int ID => PlayerState.State_Lose;

    public ActionStateLose(FSMSystem fsm, PlayerEntity role) : base(fsm, role)
    {
        
        
    }


    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();
        
        
        PlayerEntity thisPlayer = this.role as PlayerEntity;
         
       
    }
    
    
    
    public override void DoBeforeLeaving()
    {
        base.DoBeforeLeaving();
    }
}





/// <summary>
/// 攻击
/// </summary>
public class ActionStateAttack : DoubleProgressActionFSMState
{
    public override int ID => PlayerState.policeAttack;
    
    
    private const float execuateTime = 0.4f;
    public const float normalActionTime = 1f;
    
    protected float m_AttackRange;

    public ActionStateAttack(FSMSystem fsm, RoleEntity role) : base(fsm, role)
    {
        m_TotalTime = normalActionTime;
        m_ExecuteTime = execuateTime;
    }

    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();
        
#if DEBUG
        GameDebug.Log($"开始攻击  time:{this.role.battleController.time}","DoBeforeEntering","ActionFSMState",211,this.role.playerId,this.role.name);
#endif

        this.role.StopMove();
        
    }

    public override void Update()
    {
        base.Update();
        
    }

    protected override void OnExecute ()
	{
		base.OnExecute ();

     
    }

    public override void DoBeforeLeaving()
    {
        base.DoBeforeLeaving();
        
#if UNITY_EDITOR
        GameDebug.Log($"离开攻击 time：{this.role.battleController.time}");
#endif
        
    }
}

/// <summary>
/// die
/// </summary>
public class ActionStateDie : ProgressActionFSMState
{
    public override int ID => PlayerState.die;

    protected virtual float dieTime => 150f;

    public ActionStateDie(FSMSystem fsm, RoleEntity role) : base(fsm, role)
    {
        m_TotalTime = dieTime;
    }

    public override void DoBeforeEntering()
    {
        base.DoBeforeEntering();

        
        this.role.StopMove();
        this.role.rc.roleMotion.SetAnimatorInteger(State_Name,PlayerState.die);
        this.role.Rigidbody.isKinematic = true;
        this.role.Collider.isTrigger = true;
    }



    public override void Update()
    {
        base.Update();
        
    }


    public override void DoBeforeLeaving()
    {
        base.DoBeforeLeaving();

    }

}
