using Spine.Unity;
using Spine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum TargetType
{
    None = 0,
    Demonic = 1,
    Tower = 2,
    Player = 3,
    Enemy = 4,
    EnemyTower = 5,
}

public enum SearchState
{
    NoTarget = 0,//搜索范围内没有目标
    InSearchScope = 1,//在搜索范围内发现目标，但不在攻击范围内
    InAttackScope = 2,//目标在攻击范围内
}

public class Enemy : MoveCharacter
{
    public SearchTrigger searchTrigger;
    public float jumpSpeed = 10;
    public SearchState searchState;
    public float totalAttack2Time = 0.5f;
    public List<TargetType> targetTypes;
    public List<AttackInfo> attack2Infos;
    public float attackDistance;
    public bool canFly = false;
    public bool canHitFly = false;

    public Character targetCharacter;

    private void Awake()
    {
        Init();
        Debug.Log("测试");
        totalHp = 100;
        Reload();
    }

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

    public override void Reload()
    {
        base.Reload();
        ChangeSearchState(SearchState.NoTarget);
    }

    public override void FixedUpdate()
    {
        OnSearchState();
        OnState();
    }

    public Vector3 GetMoveDir()
    {
        Vector3 moveDir = Vector3.zero;
        switch (searchState)
        {
            case SearchState.NoTarget:
                moveDir = Vector3.right;
                break;
            case SearchState.InSearchScope:
                if (targetCharacter)
                {
                    if (targetCharacter.transform.position.x - transform.position.x < 0)
                    {
                        moveDir = Vector3.left;
                    }
                    else
                    {
                        moveDir = Vector3.right;
                    }
                }
                else
                {
                    moveDir = Vector3.zero;
                }
                break;
            case SearchState.InAttackScope:
                if (targetCharacter)
                {
                    if (targetCharacter.transform.position.x - transform.position.x < 0)
                    {
                        moveDir = Vector3.left;
                    }
                    else
                    {
                        moveDir = Vector3.right;
                    }
                }
                else
                {
                    moveDir = Vector3.zero;
                }
                break;
            default:
                break;
        }
        return moveDir;
    }

    public bool GetAttack()
    {
        if (searchState == SearchState.InAttackScope)
        {
            return true;
        }
        return false;
    }

    public bool GetJump()
    {
        return false;
    }

    public override void OnState()
    {
        base.OnState();
        hurtKeepTime -= Time.deltaTime;
        attackTime -= Time.deltaTime;
        Vector3 leftDir = GetMoveDir();
        bool isAttack = GetAttack();
        switch (state)
        {
            case CharacterState.Idle:
                if (isAttack)
                {
                    Attack2();
                    break;
                }
                if (!foot.TrigGround)
                {
                    if (rb.velocity.y > 0)
                    {
                        ChangeState(CharacterState.Rise);
                        break;
                    }
                    else
                    {
                        ChangeState(CharacterState.Fall);
                        break;
                    }
                }
                if (leftDir.x > 0.3f || leftDir.x < -0.3f)
                {
                    ChangeState(CharacterState.Run);
                    break;
                }
                //rb.velocity = Vector3.zero;
                break;
            case CharacterState.Run:
                if (isAttack)
                {
                    Attack2();
                    break;
                }
                if (!foot.TrigGround)
                {
                    if (rb.velocity.y > 0)
                    {
                        ChangeState(CharacterState.Rise);
                        break;
                    }
                    else
                    {
                        ChangeState(CharacterState.Fall);
                        break;
                    }
                }
                if (leftDir.x < 0.3f && leftDir.x > -0.3f)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                if (leftDir.x > 0.3f)
                {
                    //rb.velocity += Vector3.right * moveAcc * Time.deltaTime;
                    rb.velocity = Vector3.right * maxMoveSpeed;
                    //if (rb.velocity.x > maxMoveSpeed)
                    //{
                    //    rb.velocity = new Vector3(maxMoveSpeed, rb.velocity.y, rb.velocity.z);
                    //}
                    if (bodyTrans.localScale.x > 0)
                    {
                        Turn();
                    }
                }
                else if (leftDir.x < -0.3f)
                {
                    //rb.velocity -= Vector3.right * moveAcc * Time.deltaTime;
                    rb.velocity = Vector3.left * maxMoveSpeed;
                    //if (rb.velocity.x < -maxMoveSpeed)
                    //{
                    //    rb.velocity = new Vector3(-maxMoveSpeed, rb.velocity.y, rb.velocity.z);
                    //}
                    if (bodyTrans.localScale.x < 0)
                    {
                        Turn();
                    }
                }
                break;
            case CharacterState.Rise:
                if (rb.velocity.y <= 0)
                {
                    ChangeState(CharacterState.Fall);
                    break;
                }
                //if (btnJumpPress || cacheJumpTime > 0)
                //{
                //    if (!airJumped && rb.velocity.y < airJumpSpeed)
                //    {
                //        airJumped = true;
                //        AirJump();
                //        break;
                //    }
                //}
                
                rb.velocity += Vector3.up * extraRiseGravity * Time.deltaTime;
                break;
            case CharacterState.Fall:
                if (foot.TrigGround)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                //if (foot.canStepPlayers.Count > 0)
                //{
                //    Jump(jumpSpeed / 2);
                //    StepOther();
                //    break;
                //}
                //if (foot.canStepEnemyList.Count > 0)
                //{
                //    Jump(jumpSpeed / 2);
                //    StepEnemy();
                //    break;
                //}
                //if (btnJumpPress || cacheJumpTime > 0)
                //{
                //    if (!airJumped)
                //    {
                //        airJumped = true;
                //        AirJump();
                //        break;
                //    }
                //    else if (canJumpTick >= runner.Tick)
                //    {
                //        Jump();
                //        break;
                //    }
                //}
                rb.velocity += Vector3.up * extraFallGravity * Time.deltaTime;
                break;
            case CharacterState.Hurt:
                if (hurtKeepTime <= 0)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                if (!foot.TrigGround)
                {
                    rb.velocity += Vector3.up * extraFallGravity * Time.deltaTime;
                }
                rb.velocity = rb.velocity / 5 * 4;
                break;
            case CharacterState.Attack:
                if (attackTime <= 0)
                {
                    ChangeState(CharacterState.Idle);
                    break;
                }
                break;
            default:
                break;
        }
    }

    public override void ChangeState(CharacterState newState)
    {
        switch (state)
        {
            case CharacterState.Idle:
                break;
            case CharacterState.Run:
                rb.velocity = Vector3.zero;
                break;
            case CharacterState.Rise:
                break;
            case CharacterState.Fall:
                rb.velocity = Vector3.zero;
                break;
            case CharacterState.Hurt:
                break;
            case CharacterState.Attack:
                aniCollider.Play("NotAttack", 1, 0);
                break;
            case CharacterState.Die:
                isDie = false;
                break;
            default:
                break;
        }
        CharacterState oldState = state;
        state = newState;
        switch (newState)
        {
            case CharacterState.Idle:
                ani.Play("idle", 0, 0);
                aniCollider.Play("Idle", 0, 0);
                rb.velocity = Vector3.zero;
                //animalAni.SetInteger("state", (int)PlayerState.Idle);
                break;
            case CharacterState.Run:
                ani.Play("walk", 0, 0);
                aniCollider.Play("Walk", 0, 0);
                //animalAni.SetInteger("state", (int)PlayerState.Walk);
                break;
            case CharacterState.Rise:
                aniCollider.Play("Rise", 0, 0);
                break;
            case CharacterState.Fall:
                aniCollider.Play("Fall", 0, 0);
                //animalAni.SetInteger("state", (int)PlayerState.Fall);
                break;
            case CharacterState.Hurt:
                ani.Play("hitted", 0, 0);
                aniCollider.Play("Hurt", 0, 0);
                hurtKeepTime = totalHurtKeepTime;
                //ani.Play("Invincible", 2, 0);
                break;
            case CharacterState.Attack:
                break;
            case CharacterState.Die:
                ani.Play("die", 0, 0);
                aniCollider.Play("Die", 0, 0);
                isDie = true;
                break;
            default:
                break;
        }
    }

    public void Jump()
    {
        SetUpSpeed(jumpSpeed);
        ani.Play("jump", 0, 0);
    }

    public void SetUpSpeed(float speed)
    {
        ChangeState(CharacterState.Rise);
        Vector3 velocity = rb.velocity;
        Vector3 leftDir = GetMoveDir();
        if (leftDir.x > 0.3f)
        {
            if (bodyTrans.localScale.x > 0)
            {
                Turn();
            }
        }
        else if (leftDir.x < -0.3f)
        {
            if (bodyTrans.localScale.x < 0)
            {
                Turn();
            }
        }
        velocity.y = speed;
        rb.velocity = velocity;
        //animalAni.SetInteger("state", (int)PlayerState.Rise);
    }

    public void ChangeSearchState(SearchState newState)
    {
        switch (searchState)
        {
            case SearchState.NoTarget:
                break;
            case SearchState.InSearchScope:
                break;
            case SearchState.InAttackScope:
                break;
            default:
                break;
        }
        searchState = newState;
        switch (searchState)
        {
            case SearchState.NoTarget:
                targetCharacter = null;
                break;
            case SearchState.InSearchScope:
                break;
            case SearchState.InAttackScope:
                break;
            default:
                break;
        }
    }

    public bool SearchTarget()
    {
        targetCharacter = searchTrigger.GetMinDisTarget(targetTypes, canHitFly);
        if (targetCharacter != null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public void OnSearchState()
    {
        switch (searchState)
        {
            case SearchState.NoTarget:
                if (SearchTarget())
                {
                    ChangeSearchState(SearchState.InSearchScope);
                    break;
                }
                //向玩家基地移动
                break;
            case SearchState.InSearchScope:
                if (!SearchTarget())
                {
                    targetCharacter = null;
                    ChangeSearchState(SearchState.NoTarget);
                    break;
                }
                if (targetCharacter != null && Mathf.Abs(targetCharacter.transform.position.x - transform.position.x) <= attackDistance)
                {
                    ChangeSearchState(SearchState.InAttackScope);
                    break;
                }
                break;
            case SearchState.InAttackScope:
                if (targetCharacter != null)
                {
                    if (!targetCharacter.gameObject.activeInHierarchy || targetCharacter.isDie 
                        || Mathf.Abs(targetCharacter.transform.position.x - transform.position.x) > attackDistance)
                    {
                        ChangeSearchState(SearchState.NoTarget);
                    }
                }
                else
                {
                    ChangeSearchState(SearchState.NoTarget);
                }
                break;
            default:
                break;
        }
    }

    public override void BeHit(int damage, Vector3 force)
    {
        base.BeHit(damage, force);
    }

    public void Attack1()
    {
        ani.Play("attack1", 0, 0);
        aniCollider.Play("Attack1", 1, 0);
        attackTime = totalAttack1Time;
        for (int i = 0; i < attack1Infos.Count; i++)
        {
            attackTriggers[i].damage = attack1Infos[i].damage;
            Vector3 attackDir = attack1Infos[i].attackDir.normalized;
            if (bodyTrans.localScale.x < 0)
            {
                attackDir.x = -attackDir.x;
            }
            attackTriggers[i].force = attackDir * attack1Infos[i].force;
        }
        ChangeState(CharacterState.Attack);
    }

    void Attack2()
    {
        Vector3 leftDir = GetMoveDir();
        if (leftDir.x > 0.3f)
        {
            if (bodyTrans.localScale.x > 0)
            {
                Turn();
            }
        }
        else if (leftDir.x < -0.3f)
        {
            if (bodyTrans.localScale.x < 0)
            {
                Turn();
            }
        }

        ani.Play("attack2", 0, 0);
        aniCollider.Play("Attack2", 1, 0);
        attackTime = totalAttack2Time;
        for (int i = 0; i < attack2Infos.Count; i++)
        {
            attackTriggers[i].damage = attack2Infos[i].damage;
            Vector3 attackDir = attack2Infos[i].attackDir.normalized;
            if (bodyTrans.localScale.x < 0)
            {
                attackDir.x = -attackDir.x;
            }
            attackTriggers[i].force = attackDir * attack2Infos[i].force;
        }
        ChangeState(CharacterState.Attack);
    }

}
